Can C++ array end at memory boundary?

前端 未结 3 2085
谎友^
谎友^ 2021-02-12 00:38

C++ standard (and C for that matter) allows to create (not dereference though) a pointer to one element past the end of the array. Does this mean that an array will never be all

相关标签:
3条回答
  • 2021-02-12 00:47

    An implementation must allow a pointer to one past the end to exist. How it does this is its business. On many machines, you can safely put any value into a pointer, without risk (unless you dereference it); on such systems, the one past the end pointer may point to unmapped memory—I've actually encountered a case under Windows where it did.

    On other machines, just loading a pointer to unmapped memory into a register will trap, causing the program to crash. On such machines, the implementation must ensure that this doesn't happen, either by refusing to use the last byte or word of allocated memory, or by ensuring that all use of the pointer other than dereferencing it avoids any instructions which might cause the hardware to treat it as an invalid pointer. (Most such systems have separate address and data registers, and will only trap if the pointer is loaded into an address register. If the data registers are large enough, the compiler can safely load the pointer into a data register for e.g. comparison. This is often necessary anyway, as the address registers don't always support comparison.)

    Re your last question: C and C++ are exactly identical in this respect; C++ simply took over the rules from C.

    0 讨论(0)
  • 2021-02-12 00:54

    There's an interesting passage at §3.9.2/3 [Compound types]:

    The type of a pointer to void or a pointer to an object type is called an object pointer type. [...] A valid value of an object pointer type represents either the address of a byte in memory (1.7) or a null pointer (4.10).

    Together with the text at §5.7/5 [Additive operators]:

    [...] Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object.

    it seems that an array ending at the last byte in memory can not be allocated, if there is a requirement that the one-past-the-end pointer must be valid. If the one-past-the-end pointer is allowed to be invalid, I don't know the answer.

    The section §3.7.4.2/4 [Deallocation functions] states that:

    The effect of using an invalid pointer value (including passing it to a deallocation function) is undefined.

    Thus if comparing a one-past-the-end pointer for an allocated array must be supported, the one-past-the-end pointer must be valid.

    Based on the comments I got, I assume that an implementation can allocate an array without having to care about if the array's one-past-the-end pointer is usable or not. However I would like to find out the relevant passages in the standard for this.

    0 讨论(0)
  • 2021-02-12 01:04

    You're half right. Suppose a hypothetical implementation uses linearly addressed memory and pointers that are represented as 16-bit unsigned integers. Suppose also that the null pointer is represented as zero. And finally, suppose you ask to for 16 bytes of memory, with char *p = malloc(16);. Then it's guaranteed that you will get a pointer of which the numeric value is less than 65520. The value 65520 itself wouldn't be valid, because as you rightly point out, assuming the allocation succeeded, p + 16 is a valid pointer that must not be a null pointer.

    However, suppose now that a hypothetical implementation uses linearly addressed memory and pointers that are represented as 32-bit unsigned integers, but only has an address space of 16 bits. Suppose also again that the null pointer is represented as zero. And finally, suppose again that you ask for 16 bytes of memory, with char *p = malloc(16);. Then it's only guaranteed that you will get a pointer of which the numeric value is less than or equal to 65520. The value 65520 itself would be valid, so long as the implementation makes sure that adding 16 to that gives you the value 65536, and that subtracting 16 gets you back to 65520. This is valid even if no memory (physical or virtual) exists at all at address 65536.

    0 讨论(0)
提交回复
热议问题