简体   繁体   中英

Copying memory buffer to member variables of struct/class

Trying to allocate buffer from TCP/UDP message into struct/class types (with only public variables), like the one below

class book
{
   public:
    unsigned long author_code;
    int year;
    double price;
    // so on and so forth more variables
}

int main()
{
   book mybook;
   
   // recieve some bytes from tcp/udp, call it buffer

   memcpy(&mybook, &buffer, sizeof(mybook));

   return 0;
}

But when I checked the member variables, they (ie price, year) were partially correct. Some of the variables is incorrectly assigned the values. I have come across that structs and class might have incontiguous layout of memory and direct copying might not work in this case, I have to do the following for it to work

int main()
{
   book mybook;
   
   // recieve some bytes from tcp/udp, call it buffer

   int ptr = 0;
   memcpy(&(mybook.author_code), &buffer[ptr], sizeof(mybook.author_code));
   ptr += sizeof(mybook.author_code);
   memcpy(&(mybook.year), &buffer[ptr], sizeof(mybook.year));
   ptr += sizeof(mybook.year);
   memcpy(&(mybook.price), &buffer[ptr], sizeof(mybook.price));
   ptr += sizeof(mybook.price);
   // ......so on and so forth

   return 0;
}

This works but I am just wondering if there is a more simple way to do this and less error prone in terms of copying variable... have multiple data class/struct to copy to and from.

Something I have read about is using #pragma pack(push,1) that could set the boundary but I wonder what other option could I take

Thanks

The issue here is that the compiler is free to add padding between members of a struct or class in order to improve performance or for other reasons. This means that the actual memory layout of the struct or class can be different from what you expect, and simply copying the memory from one struct or class to another can result in incorrect data.

One way to deal with this is to use the #pragma pack directive to tell the compiler not to add any padding. For example:

#pragma pack(push,1)
class book
{
   public:
    unsigned long author_code;
    int year;
    double price;
    // so on and so forth more variables
};
#pragma pack(pop)

This will ensure that the memory layout of the class is exactly as you expect it to be.

Another way to deal with this is to use memcpy to copy each member of the struct or class individually, rather than trying to copy the entire struct or class at once. This is more error-prone, but it can be less work if you have a lot of structs or classes to deal with.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM