免费后,设置变量为NULL免费后,设置变量为NULL(Setting variable to NUL

2019-05-13 14:52发布

在我的公司是有编码规则说,任何释放内存后,重置变量设置为NULL。 例如 ...

void some_func () 
{
    int *nPtr;

    nPtr = malloc (100);

    free (nPtr);
    nPtr = NULL;

    return;
}

我觉得,像上面显示的代码的情况下,设置为NULL,没有任何意义。 还是我失去了一些东西?

如果在这种情况下没有意义,我要带它与“质量团队”删除此编码规则。 请指教。

Answer 1:

未使用的指针设置为NULL是一个防守风格,防范悬摆指针错误。 如果它被释放后悬摆指针被访问时,你可以阅读或覆盖随机内存。 如果一个空指针被访问时,您在大多数系统上立即得到一个崩溃,告诉你马上是什么错误。

对于局部变量,它可能是一个有点毫无意义,如果它是“显而易见”的指针没有被释放之后再访问,因此这种风格更适合于数据成员和全局变量。 即使是局部变量,它可能是一个很好的方法,如果该功能继续内存被释放后。

要完成的风格,你也应该初始化指针为NULL他们获得分配一个真正的指针值前。



Answer 2:

设置一个指向NULLfree是一个可疑的做法,往往是作为推广上显然是虚假的前提是“良好的编程”的规则。 这是属于“听起来是正确”的范畴,但在现实中实现绝对没有任何有用的(有时甚至会导致不良后果),那些假的真理之一。

据称,设置一个指向NULL后, free是应该防止可怕的“双无”的问题时,相同的指针值传递给free不止一次。 然而实际上,9例出的10时持有相同的指针值不同指针对象作为参数出现真正的“双无”的问题free 。 不用说,一个指针设置为NULLfree达到绝对没有以防止此类案件的问题。

当然,也可以使用相同的指针对象作为一个参数时,碰上“双重释放”问题free 。 然而,在这样的现实情况下,通常显示的代码的一般逻辑结构,不是一个单纯的偶然“双无”的问题。 以应对这种情况下,问题的正确方法是审查和重新思考代码的结构,为了避免这种情况,当相同的指针传递给free不止一次。 在这种情况下,设定指针NULL ,并考虑“固定”的问题,无非是企图在地毯下扫问题更多。 它根本不会在一般的情况下工作,因为代码结构的问题总是会找到另一种方式表现出来。

最后,如果你的代码是专为依靠指针值为NULL或不NULL ,这是完全没有设置指针值为NULLfree 。 但是作为一个一般的“好习惯”的规则(如“总是你的指针设置为NULLfree ”),这是再次,一个知名的好看不中用的假,往往其次是一些纯粹的宗教,巫术般的原因。



Answer 3:

大多数的答复都集中在防止双重释放,但指针设置为NULL还有另一个好处。 一旦你释放一个指针,该内存可用于通过另一次调用malloc的重新分配。 如果您仍然有原来的指针周围,你可能最终得到一个错误,如果你在这里你尝试使用后的自由和腐败的一些其他变量的指针,然后程序进入一个未知的状态和各种坏事情都可能发生(崩溃“幸运的话,数据损坏,如果你运气不好)。 如果你有自由后设置指针为NULL,任何试图通过该指针读/写以后会导致段错误,这是一般可取随机内存损坏。

由于这两个原因,它可以自由后,将指针设置为NULL是一个好主意()。 这并不总是必要的,但。 例如,如果指针变量超出范围自由(后),没有太多的理由将其设置为NULL。



Answer 4:

这被认为是很好的做法,以避免覆盖内存。 在上面的函数,这是不必要的,但通常情况下,当它完成,它可以找到应用程序错误。

尝试这样的事情,而不是:

#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

该DEBUG_VERSION让你在调试代码简介的FreeS,但两者在功能上是相同的。

编辑 :新增做......而下面的建议,谢谢。



Answer 5:

如果达到指针已免费()d,它可能会破坏或没有。 该内存可以被重新分配给你的程序的其他部分,然后你会得到内存损坏,

如果指针设置为NULL,然后如果你访问它,程序总是有段错误崩溃。 没有更多,,有时它的工作原理',没有更多的,,在unpredictible方式崩溃'。 它的调试比较容易的方式。



Answer 6:

设置指向free “D内存意味着任何试图通过该指针访问该内存将立即崩溃,而不是导致未定义行为。 这使得它更容易,以确定事情发生了错误。

我可以看到你的说法:因为nPtr在之后走出去的范围nPtr = NULL ,似乎没有成为一个理由将其设置为NULL 。 然而,在的情况下, struct成员或其他地方在指针不立即走出去的范围,它更有意义。 它不是立即显现不论该指针将被认为不应该使用它的代码被再次使用。

这是有可能的规则未做这两种情况之间的区别说明,因为它更难以自动执行规则,更不用说开发遵循它。 它不会伤害到设置指针NULL以后每隔免费的,但它指出了大问题的可能性。



Answer 7:

在C中最常见的错误是双重自由。 基本上,你做这样的事情

free(foobar);
/* lot of code */
free(foobar);

它最终会非常糟糕,操作系统尝试释放一些已经释放的内存,一般是段错误。 因此,好做法是设置为NULL ,这样就可以使测试和检查,如果你真的需要释放此内存

if(foobar != null){
  free(foobar);
}

同时要注意的是free(NULL)不会做任何事情,所以你不必写if语句。 我不是一个真正的OS大师,但我敢即使是现在大多数操作系统会崩溃双自由。

这也是一个主要的原因有垃圾收集(Java中,DOTNET)所有的语言是如此的骄傲不是有这个问题,也没有留给开发商的内存管理作为一个整体的。



Answer 8:

这背后的想法,就是停止释放的指针意外重用。



Answer 9:

这(可能)实际上是很重要的。 虽然你释放内存,程序的后面部分会分配新的东西,发生在空间降落。 您老现在的指针会指向的内存有效块。 它是那么可能有人会使用指针,导致无效程序的状态。

如果NULL出来的指针,那么任何试图使用它要提领0x0和崩溃就在那里,这是很容易调试。 随机指针指向随机内存是难以调试。 这显然不是必要的,但那么这就是为什么它是一个最佳实践文档。



Answer 10:

从ANSI C标准:

void free(void *ptr);

免费的功能使空间指向PTR被释放,也就是说,可供进一步分配。 若ptr为空指针,不会发生任何操作。 否则,如果该参数不匹配的指针早些时候释放calloc,malloc或realloc函数返回,或者如果空间已经通过调用释放释放或realloc,该行为是不确定的。

“未定义行为”几乎总是一个程序崩溃。 这样才能避免这种情况是安全的指针重置为NULL。 免费(),因为它是只传递一个指针,而不是一个指针的指针本身不能做到这一点。 你也可以写的自由()的空值指针更安全的版本:

void safe_free(void** ptr)
{
  free(*ptr);
  *ptr = NULL;
}


Answer 11:

我觉得这是有点帮助,在我的经验,当人们访问空闲内存分配它几乎总是因为他们有另一个指针到它的地方。 然后将其与其他个人编码标准,这是“避免无用的混乱”相冲突,所以我不这样做,因为我认为它很少帮助,使代码略少可读性。

然而 - 我不会将变量设置为null,如果是不应该的指针再次使用,但往往更高层次的设计给我一个理由来设置它反正空。 例如,如果指针是一个类的成员,我已经删除了它指向那么“合同”,如果你喜欢之类的是,该成员将指向有效的东西在任何时间,因此必须将其设置为null是因为。 一个小的区别,但我认为一个重要问题。

在C ++重要的是要始终想着谁拥有这个数据时,你分配一些内存(除非您使用智能指针,但即使如此,还需要一些思想)。 而这一过程往往会导致指针通常是一些类的成员,通常你想一类是处于有效状态,在任何时候,要做到这一点最简单的方法是设置成员变量为NULL指明它指向到现在什么都没有。

一个常见的模式是将所有的成员指针设置为NULL在构造函数中,并且对任何指针到您的设计说,类拥有数据析构函数调用中删除。 显然,在这种情况下,你必须将指针设置为NULL,当你删除的东西,表明你没有自己之前的任何数据。

所以总结一下,是的,我经常指针设置为NULL删除后的东西,但它作为谁拥有数据,而不是因为一个更大的设计和思想的一部分,不要盲从编码标准规则。 我认为有这样做没有任何好处并增加了“混乱”,这在我的经验是一样负责的错误和糟糕的代码,这种事情我不会在你的例子这样做。



Answer 12:

Recently I come across the same question after I was looking for the answer. I reached this conclusion:

It is best practice, and one must follow this to make it portable on all (embedded) systems.

free() is a library function, which varies as one changes the platform, so you should not expect that after passing pointer to this function and after freeing memory, this pointer will be set to NULL. This may not be the case for some library implemented for the platform.

so always go for

free(ptr);
ptr = NULL;


Answer 13:

这条规则是,当你试图避免以下情况下很有用:

1)你有复杂的逻辑和内存管理一个很长的功能,你不希望在后面的功能意外重用指针删除记忆。

2)指针是具有相当复杂的行为类的成员变量,你不希望意外重用指针删除记忆等功能。

在你的情况下,它不会使一大堆的道理,但如果功能均得到更长的时间,它可能关系。

你可能认为它设置为NULL实际上可能掩盖逻辑错误以后,或者在你认为它是有效的情况下,你仍然会崩溃NULL,所以没关系。

在一般情况下,我会建议你将它设置为NULL,当你认为这是一个好主意,当你认为它是不值得理会。 专注于写作,而不是短期的功能和精心设计的课程。



Answer 14:

要添加到其他的说什么的都有,指针使用的一个好方法是经常检查它是否是一个有效的指针或没有。 就像是:


if(ptr)
   ptr->CallSomeMethod();

明确地标记指针为NULL释放它允许这种在C / C的使用++之后。



Answer 15:

这可能是更多的初始化所有的指针为NULL的说法,但这样的事情可能是一个非常狡猾的错误:

void other_func() {
  int *p; // forgot to initialize
  // some unrelated mallocs and stuff
  // ...
  if (p) {
    *p = 1; // hm...
  }
}

void caller() {
  some_func();
  other_func();
}

p在栈因为前者在同一个地方结束nPtr ,所以它可能还含有一个看似有效的指针。 分配给*p可能会覆盖各种无关的东西,并导致难看的错误。 特别是如果编译器在调试模式下具有零局部变量初始化但不会一次优化开启。 所以调试版本不显示的bug的迹象,同时发布版本炸毁随机...



Answer 16:

设置刚刚被释放到NULL指针是不是强制性的,但一个好的做法。 通过这种方式,你可以使用一个释放指出2)无它towice避免1)



Answer 17:

设置一个指向NULL是保护agains所谓的双自由 - 一个无时()被调用一次为同一个地址更没有在该地址重新分配块的情况。

双自由导致不确定的行为 - 通常堆损坏或崩溃立即程序。 调用free()为NULL指针什么都不做,因此保证安全。

所以最好的做法,除非你现在可以肯定的是,指针免费(后叶范围会立即或很快)是设置该指针为NULL,这样即使免费()被再次调用它现在被称为一个NULL指针和未定义行为被回避。



Answer 18:

我们的想法是,如果你释放它后尝试取消引用不再视为有效的指针,要发生故障的硬盘(段错误),而不是默默地和神秘。

不过要小心。 并非所有的系统导致段错误如果取消引用NULL。 在(至少是某些版本的)AIX,*(INT *)0 == 0,和Solaris与此AIX可选兼容性 “功能。”



Answer 19:

原来的问题:设置指针释放后的内容直接NULL是完全是浪费时间,提供的代码符合所有要求,是全面的调试,并再也不会被修改。 在另一方面,防守归零已经被释放是非常有用的一个指针,当有人不假思索地增加了代码免费下)的新块(当原来模块的设计是不正确的,并且在它的情况下, -compiles,但-doesn't-DO - 什么 - 我想做的错误。

在任何系统中,存在使其最容易正确的事情的用不上的目标,并测量不准确的束缚成本。 在C语言中我们提供了一套非常尖锐,非常强大的工具,它可以在技术工人手中创造很多东西,处理不当造成,当各种隐喻的伤害。 有些是很难理解或正确使用。 和人一样,也被自然地规避风险,做不合理的事情就像调用免费使用前检查NULL值的指针...

测量的问题是,当你试图从划分不太好的,更复杂的情况好,你就越有可能得到一个模糊的测量。 如果目标是做只保留好的做法,则有些暧昧的人得到与实际并不好抛出。 如果你的目标是消除不好,那么含糊可以留在良好。 这两个目标,只保留好或消除不良清楚,似乎是截然相反,但通常有这无论是1还是其他一些双方的第三组。

之前你与质量部门的情况下,尝试寻找通过错误数据的基础上,看多久,如果有的话,无效的指针的值会引起一个必须写下来的问题。 如果你想真正的差别,是最常见的问题,在您的生产代码,并提出了三种方法来防止它



Answer 20:

原因有二:

避免崩溃时的双释放

撰稿RageZ在重复的问题 。

在C中最常见的错误是双重自由。 基本上,你做这样的事情

 free(foobar); /* lot of code */ free(foobar); 

它最终会非常糟糕,操作系统尝试释放一些已经释放的内存,一般是段错误。 因此,好做法是设置为NULL ,这样就可以使测试和检查,如果你真的需要释放此内存

 if(foobar != NULL){ free(foobar); } 

同时要注意的是free(NULL)不会做任何事情,所以你不必写if语句。 我不是一个真正的OS大师,但我敢即使是现在大多数操作系统会崩溃双自由。

这也是一个主要的原因有垃圾收集(Java中,DOTNET)所有的语言是如此的骄傲不是有这个问题,也没有留给开发商的内存管理作为一个整体的。

避免使用已释放的指针

撰稿马丁诉Löwis在另一个答案 。

未使用的指针设置为NULL是一个防守风格,防范悬摆指针错误。 如果它被释放后悬摆指针被访问时,你可以阅读或覆盖随机内存。 如果一个空指针被访问时,您在大多数系统上立即得到一个崩溃,告诉你马上是什么错误。

对于局部变量,它可能是一个有点毫无意义,如果它是“显而易见”的指针没有被释放之后再访问,因此这种风格更适合于数据成员和全局变量。 即使是局部变量,它可能是一个很好的方法,如果该功能继续内存被释放后。

要完成的风格,你也应该初始化指针为NULL他们获得分配一个真正的指针值前。



Answer 21:

当你有一个适当的质量保证团队,让我增加约QA一个小点。 有些自动化的QA工具,对C将标记分配到释放的指针为“无用分配ptr ”。 例如PC-皮棉/ FlexeLint从金培尔软件说tst.c 8 Warning 438: Last value assigned to variable 'nPtr' (defined at line 5) not used

有办法选择地抑制的消息,所以你仍然可以同时满足质量保证要求,应你的团队决定如此。



Answer 22:

它始终是可取的声明指针变量与NULL诸如

int *ptr = NULL;

比方说,PTR指向0x1000的内存地址。 使用后free(ptr)它总是明智的做法再次宣布为NULL,以抵消指针变量。 例如:

free(ptr);
ptr = NULL;

如果没有重新申报为NULL,指针变量仍保持在指向同一个地址(0x1000),这个指针变量称为悬摆指针 。 如果定义另一个指针变量(比方说,Q)和动态分配地址到新的指针,有由新指针变量取相同的地址(0x1000)的机会。 如果在情况下,您可以使用相同指针(PTR),并更新由同一个指针(PTR)指向的地址的值,则该程序将最终把值写入其中Q是指向(因为pq的地方指向同一个地址(0x1000))。

*ptr = 20; //Points to 0x1000
free(ptr);
int *q = (int *)malloc(sizeof(int) * 2); //Points to 0x1000
*ptr = 30; //Since ptr and q are pointing to the same address, so the value of the address to which q is pointing would also change.


Answer 23:

长话短说:您不希望意外(错误)访问已被释放的地址。 因为,当你释放地址,你让在堆地址被分配给其他应用程序。

但是,如果你不设置指针为NULL,并错误地尝试去参考指针,或更改地址的值; 你仍然可以做到这一点。 但不是你逻辑上想做的事情。

为什么我仍然可以访问,我已经释放的内存位置? 因为:您可能必须释放内存,但是指针变量仍对堆内存地址信息。 所以,作为一个防御性的策略,请设置为NULL。



文章来源: Setting variable to NULL after free