简体   繁体   English

C-memcpy和复制结构

[英]C - memcpy and copying structs

Ran into a design problem when using memcpy and building a generic HashTable in c. 使用memcpy并在c中构建通用HashTable时遇到设计问题。 The HashTable maps unsigned int keys to void * data that I memcpy over. 哈希表映射unsigned intvoid * ,我的数据memcpy过来。

// 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. 现在,给定struct a具有LinkedLists和指针,并且HashTable使用memcpy ,我的理解是,它复制了这些指针的浅表副本。 Thus, ht_insert mallocs space for a new entry, shallowly copies over data from a , and inserts the new entry into its table. 因此, ht_insert mallocs一个新的入口空间,从以上数据浅拷贝a ,并插入新进入其表。

Consequently, unless I free struct a completely with some function destroy_struct , I am leaking memory. 因此,除非我用某些函数destroy_struct完全释放struct a ,否则会泄漏内存。 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! 但是,考虑到我在ht_insert浅层复制数据,当我调用destroy_struct(a) ,我也会不小心释放了哈希表条目中指向的数据!

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? 上面的逻辑是否正确,如果是,是否应该使用一些递归的memcpy函数,以确保将所有数据从struct a深度复制到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. 现在,给定struct a内具有LinkedLists和指针,并且HashTable使用memcpy,我的理解是它在这些指针的浅表副本上进行复制。

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. 如果您只是将struct whatever *的内部表示形式复制到void *的内部表示形式中,那么您将遇到麻烦。 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. 您应该将一个指针转换为另一种类型,然后可以简单地对其进行分配...实际上,由于其中一种类型为void *分配将隐式发生转换。

Consequently, unless I free struct a completely with some function destroy_struct , I am leaking memory. 因此,除非我用某些函数destroy_struct完全释放struct a ,否则会泄漏内存。

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). 根据您所描述的,只需要一次 (并且只能一次 )调用free该指针值, 就可以 free该指针值,并且程序不再对其有任何用处(例如将其从哈希表中删除之后 )。 This goes for all non-null pointers that are returned by malloc , realloc or calloc . 这适用于mallocrealloccalloc返回的所有非null指针。 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. 需要说明的是:如果xy存储由这些函数之一返回的相同指针,则free应该仅在其中一个上被调用一次 因为它们包含相同的值。

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? 上面的逻辑是否正确,如果是,是否应该使用一些递归的memcpy函数,以确保将所有数据从struct a深度复制到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. 否则它无法执行任何这些操作,因为它无法编译。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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