【问题标题】:C struct memory managementC 结构内存管理
【发布时间】:2012-04-22 05:13:27
【问题描述】:

另一个C题:

假设我有一个结构,它有一个 char* 类型的指针成员。

当我想初始化一个结构体实例时,我调用malloc:

MyStruct* ptr = (MyStruct*)malloc(sizeof(MyStruct)

然后为char*成员分配256字节内存:

ptr->mem = (char*)malloc(sizeof(char)*256);

当我调用指针成员和它指向的内存时会发生什么 free(ptr);? 当我用 valgrind 检查程序时,我发现我有内存泄漏,但是当我明确调用 free(ptr->member); 时,我仍然有内存泄漏,并且 valgrind 显示“无效的免费”错误

管理成员指向的内存的正确方法是什么?

【问题讨论】:

  • 你不应该在 C 中转换来自 malloc 的返回值。
  • @stefanbachert:见stackoverflow.com/a/605858/129570
  • @stefanbachert:这是一个争论点。这不是绝对必要的,如果您没有使用选项进行编译以警告您缺少函数声明,则可能会导致错误,因为编译器假定 malloc() 返回 int 而事实并非如此。 OTOH,在 C++ 中,强制转换是必要的。我经常把演员表放进去;我理解为什么人们会忽略它,并且无论哪种方式都不要生气。
  • 我认为,问题的部分原因在于很多人使用演员表是因为他们认为自己必须演员表。他们注册它在某些代码中使用并包含它而不知道为什么。此外,我认为,在许多情况下,如果需要强制转换来澄清,那么代码的结构和/或变量的命名等有问题。再往下,我还注意到有些人也使用 malloc 强制转换来抑制错误和演员变成了某种“魔杖”——唯一的问题是它是黑魔法;)

标签: c pointers memory-management struct member


【解决方案1】:

经验法则是每次(成功)调用malloc 都需要一个free(通常,这些调用以相反的顺序发生)。

如果您只有free(ptr),那么您就有内存泄漏(因为无法访问分配给ptr->mem 的内存)。如果你只是free(ptr->mem),那么你还没有完全清理干净(不如内存泄漏那么糟糕)。

【讨论】:

    【解决方案2】:

    你必须先释放 ptr->member,然后是结构

    free(ptr->member);
    free(ptr);
    

    【讨论】:

      【解决方案3】:

      只要您调用free(ptr)ptr 中的所有成员都不再有效。你不能对他们做任何事。但是指向ptr->mem 的内存仍然需要释放。所以你必须要么先free(ptr->mem),要么把那个指针复制到某个地方,这样就有一个指向空闲的有效指针。

      分配和释放复合结构的一般模式类似于(将它们包装在执行此操作的干净函数中很有帮助):

      MyStruct* MakeMyStruct() {
          MyStruct* ptr = malloc(sizeof(MyStruct)); //N.B. don't need cast if it's C
          ptr->mem = malloc(sizeof(char)*256);
          //initialise other members
          return ptr;
      }
      
      void DestroyMyStruct(MyStruct *ptr) {
          //Free members first, then the struct
          free(ptr->mem);
          free(ptr);
      }
      

      如果某些成员本身是复杂的结构,它们将依次被分配/释放MakeWhateverDestroyWhatever,而不是上述两个函数中的mallocfree

      【讨论】:

      • +1 用于干净的功能。可以说,将ptr->mem = NULL; 添加到DestroyMyStruct 将有助于在其他地方捕获错误。
      • 这就是我实现的,但由于某种原因我得到了一个双重释放错误。valgrind 输出显示双重释放来自破坏结构的方法..
      • 可能ptr->mem 以某种方式等于ptr。你想用你的新代码更新问题吗?
      猜你喜欢
      • 2021-11-01
      • 2012-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-20
      • 2010-09-06
      • 2018-12-17
      相关资源
      最近更新 更多