c++11 - mmap and C++ strict aliasing rules -


consider posix.1-2008 compliant operating system, , let fd valid file descriptor (to open file, read mode, enough data...). following code adheres c++11 standard* (ignore error checking):

void* map = mmap(null, sizeof(int)*10, prot_read, map_private, fd, 0); int* foo = static_cast<int*>(map); 

now, following instruction break strict aliasing rules?

int bar = *foo; 

according standard:

if program attempts access stored value of object through glvalue of other 1 of following types behavior undefined:

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

what's dynamic type of object pointed map / foo ? object? standard says:

the lifetime of object of type t begins when: storage proper alignment , size type t obtained, , if object has non-trivial initialization, initialization complete.

does mean mapped memory contains 10 int objects (suppose initial address aligned)? if true, wouldn't apply code (which breaks strict aliasing)?

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

even oddly, mean declaring baz starts lifetime of (properly aligned) object of size 4?


some context: mmap-ing file contains chunk of data wish directly access. since chunk large i'd avoid memcpy-ing temporary object.


*can nullptr instead of null here, implicitly casted null? reference standard?

i believe casting violate strict aliasing. arguing convincingly above paygrade, here attempt @ workaround:

template<class t> t* launder_raw_pod_at( void* ptr ) {   static_assert( std::is_pod<t>::value, "this works plain old data" );   char buff[sizeof(t)];   std::memcpy( buff, ptr, sizeof(t) );   t* r = ::new(ptr) t;   std::memcpy( ptr, buff, sizeof(t) );   return r; } 

i believe above code has 0 observable side effects on memory , returns pointer legal t* @ location ptr.

check if compiler optimizes above code noop. so, has understand memcpy @ fundamental level, , constructing t has nothing memory there.

at least clang 4.0.0 can optimize operation away.

what we first copy bytes away. use placement new create t there. finally, copy bytes back.

we have legally created t bytes want in it.

but copy away , local buffer, has no observable effect.

the construction of object, if pod, doesn't have touch bytes either; technically bytes undefined. compilers smart "do nothing".

so compiler can work out manipulation can skipped at runtime. @ same time, have in abstract machine created object proper bytes @ location. (assuming has valid alignment! isn't code's problem.)


Comments

Popular posts from this blog

node.js - Node js - Trying to send POST request, but it is not loading javascript content -

javascript - Replicate keyboard event with html button -

javascript - Web audio api 5.1 surround example not working in firefox -