【问题标题】:free() function without malloc or calloc没有 malloc 或 calloc 的 free() 函数
【发布时间】:2011-05-05 21:02:00
【问题描述】:

快速提问

你可以使用 free() 函数而不必事先调用 malloc 吗?

ei.

void someFunc( void )
{
   char str[6] = {"Hello"};

   //some processing here ....

   free(str);
}

我没有收到任何编译错误,但这是否有效或完全正确?

谢谢,

【问题讨论】:

  • 实际上你可以使用free而不调用malloc,但前提是你传递给free的值是一个空指针。如果您想要的是一个 可能 指向已分配块,但 可能 指向本地数组的指针,那么它就没有用了。

标签: c malloc calloc


【解决方案1】:

这完全不正确:

  1. 您不能释放静态数组,例如 char str[6]
  2. free() 只能在您分配的内存(或 NULL)上调用。

【讨论】:

  • 谢谢,我会在 11 分钟内查看您的答案
  • 另请注意,正如@Emil H 所说,str 将在堆栈上分配,并在函数返回时自动释放。 @paxdiablo,是的,使用 0 或 NULL 或为 NULL 的指针调用 free() 不是问题。
【解决方案2】:

在非 malloc 的变量上使用 free 通常会导致 Segfault。示例:

#include <stdlib.h>

int main()
{
  char str[6] = {"Hello"};
  free(str);
}

$ gcc test.c -o 测试

$ ./test

分段错误

【讨论】:

  • 它确实是未定义的行为。查找这些怪癖的最佳工具是 valgrind。
  • UB UB UB! :-) 但是一个很好的“为什么这是不好的实际例子”:p
  • 如果你幸运的话,在一些平台上会出现Seg错误。实际行为将取决于在真正 malloc 块具有其堆管理结构的地址被释放的地址之前的垃圾数据。在最坏的情况下,不会发生运行时错误,但随后的 malloc() 将由于堆管理数据损坏而失败。
【解决方案3】:

当您调用 malloc() 或任何其他分配函数时,将在 heap 上分配内存。这是唯一可以释放的内存。当您声明一个静态字符串时,正如您在示例中所做的那样,该字符串在编译时分配到另一个内存段中。 str 指针本身也是如此,它分配在 stack 上,因此也无法释放。

【讨论】:

    【解决方案4】:

    没有


    free(3) 函数采用void * 参数,因此您可以将任何类型的指针传递给它而不会出现编译时错误。但是,如果指针最初不是由 malloc(3) 返回并且之前从未返回给 free(3),则会发生不好的事情。

    【讨论】:

      【解决方案5】:

      free() 使用附加到分配块的数据来管理堆。如果指向的内存不是由诸如 malloc() 或 calloc() 之类的堆分配函数分配的,那么块之前的数据将作为堆管理数据毫无意义。

      一些库会检测到无效的堆数据并产生运行时错误,否则行为未定义。在您稍后尝试分配更多内存之前,通常不会注意到此类错误的后果。这会使调试此类错误变得非常困难。

      您不会收到编译器错误,因为它不是语法错误并且在编译时无法检测到。编译器不知道库函数的语义。它只知道 malloc() 返回一个 void* 并且 free() 接受一个 void*;在编译时无法知道指针是否指向动态分配的块,因为根据定义,内存是在运行时分配的。此外,可以在运行时修改指针以指向任何内存类型,或者可以使用别名 - 复制到另一个指针,然后通过第二个指针释放。如果您期望出现错误消息,您期望很多编译器;但是,如果可能发生此类错误,某些静态分析工具可能会发出警告,而动态分析工具(例如 valgrind)可能会在测试期间以及是否实际发生错误时检测到错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-30
        • 2018-05-01
        • 2014-11-13
        • 1970-01-01
        • 2021-01-18
        • 2012-03-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多