mardi 25 juillet 2017

mmap and C++ strict aliasing rules

Consider a POSIX.1-2008 compliant operating system, and let fd be a valid file descriptor (to an open file, read mode, enough data...). The following code adheres to the C++11 standard* (ignore error checking):

void* map = mmap(NULL, sizeof(int)*10, PROT_READ, MAP_PRIVATE, fd, 0);
int* foo = static_cast<int*>(fd);

Now, does the following instruction break strict aliasing rules?

int bar = *foo;

According to the standard:

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

  • the dynamic type of the object,
  • a cv-qualified version of the dynamic type of the object,
  • a type similar (as defined in 4.4) to the dynamic type of the object,
  • a type that is the signed or unsigned type corresponding to the dynamic type of the object,
  • a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
  • an aggregate or union type that includes one of the aforementioned types among its elements or non-static data members (including, recursively, an element or non-static data member of a subaggregate or contained union),
  • a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
  • a char or unsigned char type.

What's the dynamic type of the object pointed by map / foo ? Is that even an object? The standard says:

The lifetime of an object of type T begins when: storage with the proper >alignment and size for type T is obtained, and if the object has non->trivial initialization, its initialization is complete.

Does this mean that the mapped memory contains 10 int objects (suppose that the initial address is aligned)? But if it is true, wouldn't this apply also to this code (which clearly breaks strict aliasing)?

char baz[sizeof(int)];
int* p=reinterpret_cast<int*>(&baz);
*p=5;

Even oddly, does that mean that declaring baz starts the lifetime of any (properly aligned) object of size 4?


Some context: I am mmap-ing a file which contains a chunk of data which I wish to directly access. Since this chunk is large I'd like to avoid memcpy-ing to a temporary object.


*can nullptr be instead of NULL here, is it implicitly casted to NULL? Any reference from the standard?

Aucun commentaire:

Enregistrer un commentaire