【问题标题】:C freeing struct pointer membersC 释放结构指针成员
【发布时间】:2017-07-27 13:01:37
【问题描述】:

我声明了以下结构:

typedef struct binTreeNode
{
    void *data;
    struct binTreeNode *left;
    struct binTreeNode *right;  
} myBinaryTreeNode;

在我的main 函数中,我尝试使用指向该结构的一个实例的指针root

myBinaryTreeNode *root = malloc(sizeof(myBinaryTreeNode));
printf("\nPlease insert root data: ");
int input;
scanf("%d", &input);
root->data = (void*)&input;
printInt(root->data);
free(root); 

这段代码运行得很好。但是,我认为当你有一个带有指针成员的结构时,你应该free() 每个成员(除了指向结构的指针)。

所以在这里,我没有为root->data 使用malloc(因为我认为mallocing 结构可以做到这一点),但是它被初始化为输入值并且它的值被成功打印。当我尝试free(root->data) 时,我的程序崩溃了。

所以当我malloc rootroot->data 不是malloced?如果没有,我怎么还能使用它? 为什么会这样?我在这里想念什么?

【问题讨论】:

  • So root->data is not malloced when I malloc root? If not, how can I still use it? 调用另一个 malloc 就可以了。
  • 在释放指针指向的东西之前,最好确保它是您分配的东西。您是否分配了一些东西并将结构中的指针设置为指向它?

标签: c pointers malloc free dynamic-memory-allocation


【解决方案1】:

当我尝试释放(root->data)时,我的程序崩溃了。

你不能free你没有动态分配的内存。如果你想free元素,你应该先这样分配它们:

typedef struct binTreeNode
{
    int *data;
    struct binTreeNode *left;
    struct binTreeNode *right;  
} myBinaryTreeNode;

root->data = malloc(sizeof(int));
if (root->data == NULL)
{
    printf("Error allocating memory\n");
    return;
}
scanf("%d", root->data);
free(root->data);

请注意,您应该在继续之前check the result of malloc

所以当我 malloc root 时,root->data 没有 malloced?如果没有,我怎么还能使用它?

还要注意,root->data 的空间是在您为struct 分配内存时分配的,但不是malloced。您需要一个额外的malloc,尤其是root->data,如上例所示。 root->data 需要 malloc 的原因是能够取消引用指针。

【讨论】:

    【解决方案2】:

    首先,了解您需要(或不需要)致电free() 的地点和方式。

    您不需要malloc() “for” root->data,当您分配的内存等于结构的大小时,该变量已经分配。现在,接下来,您当然需要root->data 指向一些有效内存,以便您可以取消引用要读取的指针以写入其中。您可以通过以下两种方式中的任何一种来做到这一点

    • 存储一个有效的地址(就像在你的情况下,提供一个已经存在的变量的地址)
    • 分配另一个malloc()返回的指针(成功)。

    如果您要存储malloc() 返回的指针,是的,您必须在内存中使用free(),但在您的情况下,root->data 持有malloc() 未返回的指针,因此它不需要@ 987654331@-in 之一。

    只是为了添加和强调与free()-ing 相关的部分,您不得尝试free() 之前未通过调用malloc() 分配的内存和否则,它会调用undefined behavior。引用,标准C11,第 7.22.3.3 章,(强调我的

    void free(void *ptr);
    

    free函数使ptr指向的空间被释放,也就是使 可用于进一步分配。如果ptr 是空指针,则不会发生任何操作。否则,如果 该参数与内存管理先前返回的指针不匹配 函数,,或者如果空间已通过调用 freerealloc 释放, 行为未定义。

    【讨论】:

      【解决方案3】:

      data 成员指向input 局部变量,所以你不能释放它。

      如果动态分配成员,则必须释放成员,例如

      typedef struct binTreeNode
      {
          int *data;
          struct binTreeNode *left;
          struct binTreeNode *right;  
      } myBinaryTreeNode;
      
      root->data = malloc(sizeof(int));
      scanf("%d", root->data);
      free(root->data);
      

      【讨论】:

      • 感谢您的回答!那么input 和类似的内存最终将如何被释放呢?而且,一种方法比另一种更好吗?
      • input,作为局部作用域变量,具有automatic storage
      • @OferArial input 是一个局部变量。当程序流离开变量的范围(可能是main 函数)时,关联的对象会自动销毁,并且内存会再次可用。程序退出时,全局变量被销毁。如果动态分配的对象不是freed,则它们永远不会被销毁,尽管现代操作系统会在程序退出后从程序中回收内存。但是析构函数永远不会被执行,这对于拥有更多资源而不仅仅是内存的类来说可能是不好的。
      • @PeterA.Schneider 非常感谢您提供的详细信息。那么局部变量在内存中保存在哪里呢?在堆栈上?如果不是,谁来摧毁它们?
      • @LPs 是的,没错,但前提是你不看;-)。
      【解决方案4】:

      我在您的代码中添加了一些注释。

      我希望这能解决问题。

      // I have added an enclosing block for the purpose of demonstration:
      {
          // Here you allocate memory for a tree node object with dynamic/allocated 
          // storage duration.
          // That is: three pointers, that point to nowhere are created and will
          // exist until the memory holding them is free'd.
          myBinaryTreeNode *root = malloc(sizeof(myBinaryTreeNode));
          printf("\nPlease insert root data: ");
          // Here you create an object with automatic storage duration.
          // That is, the object is automatically destroyed when the function
          // returns or the block is closed: { ... }
          int input;
          // here you attempt to assign a value to the variable
          // (you should check the return value: the input may fail)
          scanf("%d", &input);
          // Here you assign the address of an object to a pointer.
          // Note that you are only allowed to use the pointer as long as the
          // object it points to "lives".
          root->data = (void*)&input;
          // Here you probably print the value, or the pointer address, or something else
          printInt(root->data);
          free(n); // <-- Where and how did you allocate this?
          // Here you free the memory holding the tree node
          free(root); 
      } // <-- At this point the "input" variable is automatically destroyed.
      

      您应该真正了解不同的存储持续时间(自动和动态/分配)以及动态内存分配的目的:


      详细解答问题:

      当我尝试free(root-&gt;data) 时,我的程序崩溃了。

      那是因为你只能free() 你所拥有的malloc()。对于不同类型的存储时长,内存管理是不同的。

      所以root-&gt;data在我malloc root时没有malloced?

      为指针分配内存,但默认情况下它不“拥有”或“指向”任何对象。

      如果没有,我怎么还能使用它?

      就像你做的那样。您为它分配一个对象的内存地址,该地址的寿命足以让您使用它。您可以使用动态内存管理生成此类对象(然后注意在完成后手动销毁它:不要泄漏内存)或使用“自动内存管理”(然后注意它不是过早销毁:不要访问无效内存)。 (仅列举两种创建对象的可能方式……)

      【讨论】:

        猜你喜欢
        • 2015-07-28
        • 1970-01-01
        • 1970-01-01
        • 2021-06-23
        • 2023-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多