Creating invalid link through reinterpret

I am trying to determine if the following code causes undefined behavior:

#include <iostream> class A; void f(A& f) { char* x = reinterpret_cast<char*>(&f); for (int i = 0; i < 5; ++i) std::cout << x[i]; } int main(int argc, char** argue) { A* a = reinterpret_cast<A*>(new char[5]) f(*a); } 

I understand that reinterpret_cast to and from char* compatible, because the standard allows overlay using char and unsigned char pointers (my selection):

If the program tries to access the stored value of the object through an l value other than one of the following types, the behavior is undefined:

  • dynamic type of object
  • cv-qualified version of the dynamic type of an object,
  • a type that is a signed or unsigned type corresponding to a dynamic type of an object,
  • a type that is a signed or unsigned type corresponding to the receipt version of the dynamic type of an object,
  • a collection or type of association that includes one of the above types among its members (including recursively, a member of a subgroup, or a union)
  • a type that is (possibly cv-qualified) a base class type of a dynamic object type,
  • a char or unsigned char .

However, I'm not sure if f(*a) causes undefined behavior by creating an A& reference to an invalid pointer. The decisive factor, apparently, is that it "tries to gain access" to the word formation tools in the context of the C ++ standard.

My intuition is that this is not access, since access will require A to determine (it is declared, but not defined in this example). Unfortunately, I cannot find a specific definition of "access" in the C ++ standard:

Does f(*a) perform undefined behavior? What does β€œaccess” mean in the C ++ standard?

I understand that, regardless of the answer, it is hardly worth relying on this behavior in production code. I ask this question primarily out of a desire to improve my understanding of the language.

[Edit] @SergeyA quoted this section of the standard. I have included it here for easy reference (emphasis mine):

5.3.1 / 1 [expr.unary.op]

The unary operator * performs an indirect call: the expression to which it is applied must be a pointer to the type of the object or a pointer to the type of the function, and the result is the value l related to the object or function, the point of expression. If the type of the expression is a "pointer to T ", then the result type is " T ". [Note: it is incorrect to indicate a pointer to an incomplete type (except for cv void). The lval thus obtained can be used in a limited way (for example, to initialize a link); this lvalue value should not be converted to prvalue, see 4.1. - end of note]

Tracking the link to 4.1, we find:

4.1 / 1 [conv.lval]

The value gl (3.10) of a non-function type without an array T can be converted to prvalue. If T is an incomplete type, a program that requires this conversion is poorly formed. If T is a non-class type, the prvalue type is a cv-unqualified version of T Otherwise, the prvalue type will be T

When the lvalue-rvalue transform is applied to the expression e and either:

  • e not evaluated potentially, or
  • evaluating e leads to evaluating the term ex set of potential results e , and ex denotes the variable x , which is not odr-used ex (3.2)

the value contained in the reference object is not available .

I think our answer is whether *a satisfies the second point of the marker. I had a problem analyzing this state, so I'm not sure.

+5
source share
1 answer

char* x = reinterpret_cast<char*>(&f); . Or, more precisely, access through x allowed - the listing itself is always valid.

A* a = reinterpret_cast<A*>(new char[5]) invalid - or, to be precise, access through a will lead to undefined behavior.

The reason for this is that although it works fine to access an object using char* it is not possible to access an array of characters through a random object. The standard allows first, but not second.

Or, in unprofessional conditions, you can use the type* alias through char* , but you cannot use the char* alias through type* .

EDIT

I just noticed that I did not answer the direct question ("What is" access "in the C ++ standard"). Apparently, the standard does not define access (at least I could not find a formal definition), but pointer dereferencing is usually understood to mean access.

+3
source

Source: https://habr.com/ru/post/1246574/


All Articles