-1

I have the content of a file already loaded in memory and I want to assign the data from the file to a convenient set of structs, and I don´t want to allocate new memory.

So I have the pointer of the memory where the data from the file starts, from there I work down this pointer assigning the values to different structs but then I reach a point where the program crashes.

//_pack_dynamic is the pointer to the data in memory
us *l_all_indexes = (us *) _pack_dynamic; //us is an unsigned short

printf("Index 0:%d", l_all_indexes[0]); //here is where the program crashes

_pack_dynamic += sizeof(us) * m_number_of_indexes;

The data, at least for the first element, is there, I can get it out like so:

us temp;
memcpy(&temp, _pack_dynamic, sizeof(us));

Any idea how I could extract all the indexes (m_number_of_indexes) from _pack_dynamic and assign them to l_all_indexes without allocating new memory?

SergeyA
  • 61,605
  • 5
  • 78
  • 137
Walrfi
  • 113
  • 6
  • The structs are packed and the data is aligned correctly, yeah? – Joe Aug 09 '17 at 15:23
  • What's `us` ? Why it can be printed? Also I see some missing parentheses. – Eugene Sh. Aug 09 '17 at 15:24
  • Yes. I packed the file in python using little-endian (it is for a little endian processor). Before, I had it working with new memory allocations but decided to get rid of that. – Walrfi Aug 09 '17 at 15:26
  • @ Eugene Sh "us" in an unsigned short, sorry I missed a parentheses on the printf while copyng the data (the code compiles) – Walrfi Aug 09 '17 at 15:28
  • In C++ it's undefined behaviour, use `std::memcpy` instead. It might also be UB in C you will need to check the standard. – Richard Critten Aug 09 '17 at 15:28
  • @ Richard Critten How would extract the array from _pack_dynamic (it has m_number_of_indexes elements) and paste it on l_all_indexes) without allocating new more memory? – Walrfi Aug 09 '17 at 15:30
  • Its not possible – kocica Aug 09 '17 at 15:40
  • what type of pointer is `_pack_dynamic`? Looks like this violates [strict aliasing rules](https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule) – yano Aug 09 '17 at 15:45
  • @yano the type is void * – Walrfi Aug 09 '17 at 15:48
  • you can use a `union` to associate the pointers together, something like `union{ void* _pack_dynamic; us* _pack_dynamic_us; };`, then use the `us*` when you need it,, I think that will correct your UB. If you're still crashing after that obviously there's other problems. – yano Aug 09 '17 at 15:55
  • @ yano Didn´t know you could do that, thanks for the tip! I have a bunch of different types (not only us) so I guess it would have to go back to memory allocation and memcpy – Walrfi Aug 09 '17 at 16:01
  • Sure,, take a look at the strict aliasing link in my previous comment and do some googling for "type punning" – yano Aug 09 '17 at 16:09
  • "extract all" --> `us extract[m_number_of_indexes]; memcpy(extract, _pack_dynamic, sizeof *extract * m_number_of_indexes);` – chux - Reinstate Monica Aug 09 '17 at 18:26

1 Answers1

0

Accessing _pack_dynamic as if it contained us object(s) has undefined behaviour unless it actually does contain such objects (this is a slight simplification, but a good rule of thumb. An array of char certainly cannot be interpreted as short).

The memcpy way into a proper us object is the only standard way to interpret memory as an object. Another approach for integers is to read char by char and shift-mask-or them together. This approach allows assuming a particular endianness instead of native.

A system dependent way that might work is to make sure that _pack_dynamic is aligned to the boundary required by us. But even then, standard gives you no guarantees about behaviour.

"Allocating" an automatic variable has hardly any runtime overhead. Allocating a few bytes for a short is usually insignificant.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • ok, thanks for the explanation, I guess I will have to go back to previous version and allocate new memory and use memcpy instead. – Walrfi Aug 09 '17 at 15:46