【问题标题】:Function free() in C isn't working for meC 中的函数 free() 对我不起作用
【发布时间】:2011-12-08 03:14:27
【问题描述】:

我一直在尝试使用free() 释放通过malloc() 分配的内存。

它确实释放了一些结构,但保留了一些原样,并且它们还保持与子级的链接。它也永远不会为二叉树释放根(gRootPtr)

我正在使用 Xcode 来查找二叉树使用的内存是否已被释放,并使用 if 语句。

我用来释放内存的代码:

void FreeMemory(InfoDefiner *InfoCarrier)
{
    if ((*InfoCarrier) != NULL) {
        FreeMemory((&(*InfoCarrier)->left));
        FreeMemory((&(*InfoCarrier)->right));
        free((*InfoCarrier));
    }
}

我用来查看内存是否已被释放的代码。

if (gRootPtr != NULL) {
    return 1;
}
else{
    return 0;
}

【问题讨论】:

  • C 中的 Function Free() 不起作用 - 是的,是的。
  • if ((*InfoCarrier) != NULL)` 比较 InfoDefiner 是否为 NULL,而不是指针是否为 NULL。
  • 一般来说,您可以假设如果一个标准库函数(尤其是像 free 这样与编码一样不可或缺的函数)“不起作用”,那么您做错了什么.
  • 欢迎来到 Stack Overflow!为了清楚起见,我已尽我所能编辑了您的问题。请检查我的编辑以确保您的问题仍然反映您要解决的问题。将来,在提问时尽量做到更清晰、更具体。一些关于提问的好技巧可以found here

标签: c malloc free std


【解决方案1】:

该检查不会检查变量是否被释放。请注意,free(pointer) 不会将该指针设置为 NULL。如果你想这样,你必须自己设置它,这是C中的一个常见习语:

free(pointer);
pointer = NULL;

表示您已经释放了该指针。

【讨论】:

    【解决方案2】:

    Calling free does not set the pointer to NULL。你必须自己做。

    7.21: 为什么调用free()后指针不是空的?
        之后使用(分配,比较)指针值有多不安全
        它被释放了吗?
    
    A:调用free()时,传入的内存指向的
        指针被释放,但调用者中指针的值
        可能保持不变,因为 C 的按值传递语义
        意味着被调用的函数永远不会永久改变值
        他们的论点。 (另见问题 4.8。)
    
        一个被释放的指针值,严格来说,
        无效,并且*任何*使用它,即使它没有被取消引用,
        理论上可能会导致麻烦,尽管作为
        实施问题,大多数实施可能不会去
        以他们的方式为无害的使用生成异常
        无效的指针。
    
        参考文献:ISO Sec。 7.10.3;理由二。 3.2.2.3.

    【讨论】:

      【解决方案3】:

      首先,free 不会改变指针本身。

      void *x = malloc(1);
      free(x);
      assert(x != NULL); // x will NOT return to NULL
      

      如果您希望指针返回 NULL,您必须自己执行此操作。

      第二,free后指针指向的内存会发生什么,没有任何保证:

      int *x = malloc(sizeof(int));
      *x = 42;
      free(x);
      // The vlaue of *x is undefined; it may be 42, it may be 0,
      // it may crash if you touch it, it may do something even worse!
      

      请注意,这意味着如果free() 有效,您无法实际测试。严格来说,free() 完全不做任何事情来实现是合法的(当然,如果是这种情况,你最终会耗尽内存)。

      【讨论】:

        【解决方案4】:

        函数free 接受一个指向已分配内存的指针,但它并没有将该指针设置为NULL,事实上它没有办法这样做(它需要为此获取指针的地址)。

        此场景中的典型用例是:

        free(myptr);
        myptr = NULL;
        

        【讨论】:

          【解决方案5】:

          free() 失败的唯一原因是您给它的指针没有取消对已分配堆的引用。此行为已明确定义,free() 要么工作,要么您的程序将因访问冲突而停止。

          为了这个目的,在释放指针后重新初始化指针是一种很好的做法。这让您:

          • 确保不要在已分配的指针之上进行分配(从而丢失对原始块的引用并导致泄漏)(尽管有 realloc())。

          • 确保您没有释放最近释放的内存或从未分配过的内存

          通过测试指针是否已初始化(或为 NULL),两者都变得容易。

          最好手动执行此操作并养成这样做的习惯。我已经看到了一些非常复杂的重新实现free() 的方法,以便自动重新初始化指针,就像这个小宝石也试图避免释放未分配的内存:

          void safe_free(void **p)
          {                    
                  if (*p != NULL) {
                          free(*p);
                          *p = NULL;
                  }                 
          }
          

          请,不要使用该代码,由于取消引用类型双关指针,它会在严格的平台上严重破坏。另外,如果指针是字符串文字怎么办?

          相反,只需确保跟踪指针并在释放后对其进行初始化。

          【讨论】:

            猜你喜欢
            • 2021-03-28
            • 2021-12-29
            • 2023-01-22
            • 2011-08-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多