Alp*_*neo 146 c malloc free coding-style heap-memory
在我的公司中,有一个编码规则,在释放任何内存后,将变量重置为NULL.例如 ...
void some_func ()
{
int *nPtr;
nPtr = malloc (100);
free (nPtr);
nPtr = NULL;
return;
}
Run Code Online (Sandbox Code Playgroud)
我觉得,在上面显示的代码中,设置为NULL没有任何意义.或者我错过了什么?
如果在这种情况下没有任何意义,我将采用"质量团队"来删除此编码规则.请指教.
Mar*_*wis 278
将未使用的指针设置为NULL是一种防御方式,可防止悬空指针错误.如果在释放后访问悬空指针,则可以读取或覆盖随机存储器.如果访问空指针,则会在大多数系统上立即崩溃,立即告诉您错误是什么.
对于局部变量,如果在释放后指针不再被访问是"显而易见的",那么它可能有点无意义,因此这种样式更适合于成员数据和全局变量.即使对于局部变量,如果在释放内存后函数继续,也可能是一个好方法.
要完成样式,还应该在为指定真值指针值之前将指针初始化为NULL.
AnT*_*AnT 36
设置指向NULLafter 的指针free是一种可疑的做法,通常在明显错误的前提下被普及为"良好编程"规则.这是属于"声音正确"类别的那些假真相之一,但实际上绝对没有任何用处(有时会导致负面后果).
据称,当指针值传递给多次时,设置指向NULLafter 的指针free应该可以防止可怕的"双重自由"问题free.但实际上,在10个中的9个案例中,当具有相同指针值的不同指针对象用作参数时,会发生真正的"双重自由"问题free.不用说,设置指针指向NULL后free达到绝对没有以防止此类案件的问题.
当然,当使用相同的指针对象作为参数时,可能会遇到"双重自由"问题free.然而,实际上这种情况通常表明代码的一般逻辑结构存在问题,而不仅仅是意外的"双重自由".在这种情况下处理问题的正确方法是检查并重新考虑代码的结构,以避免在同一指针被free多次传递时的情况.在这种情况下,设置指针NULL并将问题视为"固定"只不过是试图扫除地毯下的问题.它在一般情况下根本不起作用,因为代码结构的问题总是会找到另一种表现方式.
最后,如果你的代码专门设计为依赖于指针值,那么将指针值设置为after 就完全NULL没NULL了问题.但作为一个普遍的"良好实践"规则(如"总是把你的指针设置在后面"),它再一次是一个众所周知的,相当无用的假货,往往是一些纯粹的宗教,巫术般的原因.NULLfreeNULLfree
小智 32
大多数响应都集中在防止双重释放,但将指针设置为NULL还有另一个好处.释放指针后,可以通过另一次调用malloc来重新分配该内存.如果你仍然有原始指针你可能最终得到一个错误,你试图在释放后使用指针并破坏其他变量,然后你的程序进入一个未知状态,可能发生各种坏事(如果你崩溃"幸运的是,如果你运气不好,数据就会被破坏".如果在释放后将指针设置为NULL,则稍后通过该指针读取/写入的任何尝试都将导致段错误,这通常比随机内存损坏更可取.
出于这两个原因,在free()之后将指针设置为NULL是个好主意.但这并不总是必要的.例如,如果指针变量在free()之后立即超出范围,则没有太多理由将其设置为NULL.
raz*_*zed 19
这被认为是避免覆盖内存的好习惯.在上面的函数中,它是不必要的,但通常在完成时它可以找到应用程序错误.
尝试这样的事情:
#if DEBUG_VERSION
void myfree(void **ptr)
{
free(*ptr);
*ptr = NULL;
}
#else
#define myfree(p) do { void ** __p = (p); free(*(__p)); *(__p) = NULL; } while (0)
#endif
Run Code Online (Sandbox Code Playgroud)
DEBUG_VERSION允许您在调试代码中分析释放,但两者在功能上是相同的.
编辑:添加了...,如下所示,谢谢.
将指针设置为free'd存储器意味着通过指针访问该存储器的任何尝试都将立即崩溃,而不是导致未定义的行为.它可以更容易地确定出错的地方.
我可以看到你的论点:因为nPtr它刚刚超出范围nPtr = NULL,似乎没有理由将它设置为NULL.但是,struct对于指针不会立即超出范围的成员或其他位置,它更有意义.目前还不清楚该指针是否会被不应该使用它的代码再次使用.
可能会在不对这两种情况进行区分的情况下声明规则,因为自动执行规则要困难得多,更不用说让开发人员遵循规则了.NULL在每次免费之后设置指针并没有什么坏处,但它有可能指出大问题.
如果你到达了free()d的指针,它可能会破坏.该内存可能会重新分配给您的程序的另一部分,然后您会得到内存损坏,
如果将指针设置为NULL,那么如果您访问它,程序将始终崩溃并出现段错误.没有更多,有时候它会起作用',不再是,以不可预测的方式崩溃''.它更容易调试.
c中最常见的错误是双重免费.基本上你做那样的事情
free(foobar);
/* lot of code */
free(foobar);
Run Code Online (Sandbox Code Playgroud)
它最终非常糟糕,操作系统尝试释放一些已经释放的内存,通常是段错误.所以好的做法是设置NULL,所以你可以进行测试并检查你是否真的需要释放这些内存
if(foobar != null){
free(foobar);
}
Run Code Online (Sandbox Code Playgroud)
还要注意的是,free(NULL)不会做任何事情,所以你不必编写if语句.我不是一个真正的操作系统大师,但我现在甚至相当大多数操作系统会在双重免费时崩溃.
这也是为什么所有带垃圾收集的语言(Java,dotnet)为没有这个问题而感到骄傲的主要原因,也没有必要让开发人员整个内存管理.
小智 6
最近我在寻找答案后遇到了同样的问题。我得出这样的结论:
这是最佳实践,必须遵循这一做法才能使其在所有(嵌入式)系统上可移植。
free()是一个库函数,它会随着平台的变化而变化,因此您不应期望在将指针传递给该函数并释放内存后,该指针将被设置为 NULL。对于为该平台实现的某些库来说,情况可能并非如此。
所以总是追求
free(ptr);
ptr = NULL;
Run Code Online (Sandbox Code Playgroud)
这实际上很重要。尽管您释放了内存,但程序的后续部分可能会分配恰好落在该空间中的新内容。您的旧指针现在将指向有效的内存块。那么有人可能会使用该指针,从而导致无效的程序状态。
如果您将指针设为 NULL,那么任何使用它的尝试都会取消引用 0x0 并在那里崩溃,这很容易调试。指向随机内存的随机指针很难调试。这显然是没有必要的,但这就是为什么它出现在最佳实践文档中。
来自 ANSI C 标准:
void free(void *ptr);
Run Code Online (Sandbox Code Playgroud)
free 函数导致 ptr 指向的空间被释放,即可供进一步分配。如果 ptr 是空指针,则不会发生任何操作。否则,如果参数与 calloc 、 malloc 或 realloc 函数先前返回的指针不匹配,或者空间已通过调用 free 或 realloc 释放,则行为未定义。
“未定义的行为”几乎总是程序崩溃。为了避免这种情况,可以安全地将指针重置为 NULL。free() 本身不能执行此操作,因为它仅传递一个指针,而不是指向指针的指针。您还可以编写一个更安全的 free() 版本,将指针设为 NULL:
void safe_free(void** ptr)
{
free(*ptr);
*ptr = NULL;
}
Run Code Online (Sandbox Code Playgroud)