How does an unspecified pointer conversion behave in C++14?

379 views Asked by At

The result of some pointer casts are described as unspecified. For example, [expr.static.cast]/13:

A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T,” [...] If the original pointer value represents the address A of a byte in memory and A satisfies the alignment requirement of T, then the resulting pointer value represents the same address as the original pointer value, that is, A. The result of any other such pointer conversion is unspecified.

My question is: in the case where alignment is not satisfied, what are the possible results?

For example, are the following results permitted?

  • a null pointer
  • an invalid pointer value (i.e. pointer which does not point to allocated storage of size T)
  • a valid pointer to a T in a completely separate part of memory

Code sample for reference:

#include <iostream>

int main(int argc, char **argv)
{
    int *b = (int *)"Hello, world";   // (1)

    *b = -1;                           // (2)
    std::cout << argc << '\n';
}

Line (1) triggers my above quote from [expr.static.cast]/13 because it is a reinterpret_cast which is covered by [expr.reinterpret.cast]/7 which defines the conversion in terms of static_casting through void *.

If the unspecified result may be an invalid pointer value, then line (1) may cause a hardware trap. (Reference: N4430 which clarifies similar wording that was in C++14 and C++11).

Corollary question: is there any case in which line 1 would cause undefined behaviour? (I don't think so at this stage; since C++14 invalid pointer value reading is implementation-defined or causes a hardware trap).


Also interesting is that line (2) would in most cases be undefined behaviour due to strict aliasing violation (and perhaps other reasons too), however if the unspecified result may be &argc then this program could output -1 without triggering undefined behaviour!

1

There are 1 answers

5
Shafik Yaghmour On

My question is: in the case where alignment is not satisfied, what are the possible results?

As far as I can tell N4303: Pointer safety and placement new partially answers this question, although somewhat indirectly. This paper refers to CWG issue 1412: Problems in specifying pointer conversions which brought about the changes to [expr.static.cast]/13 that you reference, specifically adding:

[...]If the original pointer value represents the address A of a byte in memory and A satisfies the alignment requirement of T, then the resulting pointer value represents the same address as the original pointer value, that is, A. The result of any other such pointer conversion is unspecified.[...]

In reference to this change N4303 says (emphasis mine):

Prior to the adoption of the resolution for DR 1412 [CWG1412], the value of bp is unspecified at the point of its initialization and its subsequent passing to operator new via the new-expression. Said pointer may be null, insufficiently aligned or otherwise dangerous to use.

So an unspecified conversion can results in:

  • A null pointer
  • An insufficiently aligned pointer
  • A pointer that is dangerous to use