简体   繁体   中英

C - memcpy and copying structs

Ran into a design problem when using memcpy and building a generic HashTable in c. The HashTable maps unsigned int keys to void * data that I memcpy over.

// Random example
void foo() {

  // Suppose `a` is a struct that contains LinkedLists, char arrays, etc
  // within it.
  struct *a = malloc(sizeof(a));
  HashTable ht = ht_create(sizeof(a));

  // Insert the (key, value) pair (0, a) into the hash table ht
  ht_insert(ht, 0, a);

  // Prevent memory leak
  destroy_struct(a);

  // Do stuff...

  // ... eventually destroy ht
  ht_destroy(ht);
}

Now, given struct a has LinkedLists and pointers within it, and the HashTable is using memcpy , my understanding is that it copies over shallow copies of these pointers. Thus, ht_insert mallocs space for a new entry, shallowly copies over data from a , and inserts the new entry into its table.

Consequently, unless I free struct a completely with some function destroy_struct , I am leaking memory. However, given I'm shallowly copying data in ht_insert , when I call destroy_struct(a) , I will have accidentally freed the data pointed to within the hash table's entry as well!

Is the logic above correct, and if so, should I use a some recursive memcpy function that makes sure to deep copy all data from struct a to the HashTable?

Firstly, if your code doesn't reproduce the problem you are explaining, you shouldn't include it. The problem your code produces is compiler errors. This doesn't help your question, does it?

Now, given struct a has LinkedLists and pointers within it, and the HashTable is using memcpy, my understanding is that it copies over shallow copies of these pointers.

If you are simply copying the internal representation of a struct whatever * into the internal representation of a void * , then you are asking for trouble. There is no guarantee that the two representations are identical. It's possible that one pointer type might be larger than the other, that they use different endianness (if they're implemented as typical quasi-integers) or other internal differences might exist. You should convert one pointer to the other type, and then you could simply assign it... In fact, because one of the types is void * that conversion will happen implicitly when you assign.

Consequently, unless I free struct a completely with some function destroy_struct , I am leaking memory.

From what you have described, you should only call free on that pointer value once (and only once ) you are done with it, and your program no longer has any use for it (eg after you have removed it from the hashtable). This goes for all non-null pointers that are returned by malloc , realloc or calloc . To clarify: if x and y store the same pointer returned by one of those functions, free should only be called ONCE on ONE OF THEM because they contain the same value.

Is the logic above correct, and if so, should I use a some recursive memcpy function that makes sure to deep copy all data from struct a to the HashTable?

I highly recommend breaking this question up into two or more separate questions, because it's double-barreled. I could simply answer "yes" (or "no"). Would that give you any meaningful information?

This brings me back to what I first wrote. I can only guide you based on what you've written here, which might not be reflective of the code that you use (especially given the influences of the erroneous code you've given). In order to guide you better, I would need to see all of the gaps filled in. I would need to see a testcase that creates a hashtable, inserts into the hashtable, uses the hashtable, removes from the hashtable and cleans up the hashtable to determine whether or not your operations are leaking anywhere... but most importantly, this testcase would need to be COMPILABLE ! Otherwise it can't do any of those things, because it can't compile.

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