安装变量 NULL 解放后

在我公司,有一个编码规则,指出,在发布任何内存之后,丢失变量
NULL

. 例如 ...


void some_func // 
{
int *nPtr;

nPtr = malloc /100/;

free /nPtr/;
nPtr = NULL;

return;
}


在这种情况下,我觉得在上面显示的代码,设置值
NULL

没关系。 或者我错过了什么?

如果在这种情况下没有任何意义,我将接受它 "quality team", 删除此编码规则。 请指教。
已邀请:

裸奔

赞同来自:

将未使用的指针安装到NULL是一种保护样式,可防止挂起指针错误。 如果在其发布后执行对挂起指针的访问,则可以读取或覆盖任意内存。 何时参考指针 null 在大多数系统中,您立即进行了立即失败,立即告诉您错误是什么。

对于局部变量,如果它可能会略微毫无意义 "obvious", 发布后,指针不再可用,因此此样式更适合成员数据和全局变量。 即使对于局部变量,如果函数在释放内存之后继续,这可能是一个好的方法。

要完成样式,您还必须初始化指针 NULL, 在分配指针的真实值之前。

裸奔

赞同来自:

安装指针
NULL


free

- 练习练习,通常是一项规则很受欢迎 "good programming" 在明显的假背景上。 这是属于该类别的虚假真理之一。 "sounds right", 但实际上,绝对没有什么用 /有时会导致负面后果/.

大概是安装指针
NULL


free

必须防止一个可怕的问题 "double free", 当传输相同的指针值时
free

不止一次。 但是,事实上 9 案件出来 10 真正的问题 "double free" 作为论点发生
free

使用

不同的

指向包含相同指针值的指针对象 . 不用说安装指针
NULL


free

绝对没有任何东西可以在这种情况下防止问题。

当然,你可以遇到一个问题 "double free" 使用相同的指针对象作为参数
free

. 然而,实际上,这种情况通常通常表明代码的整体逻辑结构的问题,而不仅仅是随机的问题 "double free". 解决此类情况下解决问题的正确方法是修改并重新思考代码结构以避免发送相同指针的情况
free

不止一次。 在这种情况下,安装指针
NULL

并考虑问题 "fixed"- 只不过是在地毯下倾斜这个问题的东西。 一般来说,它根本就是不起作用,因为代码结构的问题将始终找到另一种方式来表达自己。

最后,如果您的代码专门设计为 , 依靠指针的值
NULL

或不
NULL

, 将指针值设置为非常正常
NULL


free

. 但作为一般规则 "good practice" /怎么样 "始终安装指针
NULL


free

"/ 这个,又称,众所周知,毫无用处的假装,其次是一些纯粹的宗教,Voudist的原因。

君笑尘

赞同来自:

大多数答案都集中在防止双重免费,但是安装指针 NULL 它有一个优势。 一旦释放指针,此内存将被另一个通话重新分配。 malloc. 如果您仍然有初始指针,则在释放和损坏其他变量后尝试使用指针时可能会遇到错误,然后您的程序进入未知状态,可能会发生所有类型的坏事 /如果你很幸运,那么数据损坏,如果你不是幸运的话/. 如果您设置了指针 NULL 后 free, 任何阅读尝试/通过此指针的记录后来会导致 segfault, 通常优于随机损坏记忆。

在两个原因,建立指针可能是一个好主意 NULL 后 free//. 但并不总是必要的。 例如,如果指针变量之后立即退出范围 free//, 没有特别的理由安装它 NULL.

江南孤鹜

赞同来自:

避免重写内存被认为是良好的做法。 在上面的功能中,它不是必需的,但通常在完成时,它可以找到应用程序错误。

尝试这样的东西:


#if DEBUG_VERSION
void myfree/void **ptr/
{
free/*ptr/;
*ptr = NULL;
}
#else
#define myfree/p/ do { void ** p_tmp = /p/; free/*/p_tmp//; */p_tmp/ = NULL; } while /0/
#endif


DEBUG_VERSION 允许您在调试代码中配置免费空间,但两个都在功能相等。

编辑

: 添加到做 ... 虽然如下,谢谢。

帅驴

赞同来自:

c中最常见的错误是 double free. 基本上你做了这样的事情


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


它结束得非常糟糕, OS 试图释放一些发布的内存并一般 segfault. 因此,良好的做法是设定价值
NULL

, 所以你可以做测试并检查你是否真的需要释放这个内存


if/foobar != null/{
free/foobar/;
}


还应该指出的是
free/NULL/

什么都没有,所以你不需要写 if statement. 我不是一个真主 OS, 但我甚至是现在的大多数 OSes 会崩溃 double free.

这也是为什么所有语言与垃圾收集的主要原因 /Java, dotnet/ 因此,他们感到自豪,他们没有这个问题,以及他们不需要让开发人员一般管理内存的事实。

董宝中

赞同来自:

将指针安装到内存
free

'd 这意味着任何通过折叠立即终止访问此内存的任何尝试都会立即终止,并且不会导致无限行为。 这极大地促进了一切都出错的定义。

我可以理解你的论点:自从
nPtr

后立即出现范围
nPtr = NULL

, 没有理由安装它
NULL

. 但是,就成员而言
struct

或其他地方,指针不会立即留下范围,它有更多的意义。 它不是立即可见的,无论是不应使用的代码都将使用该指针是否使用。

规则可能是在没有执行这两种情况的情况下的差异的情况下制定,因为自动应用规则更难,更不用说开发人员跟随他。 没有伤害建立指针
NULL

在每次免费之后,但它有可能表明大问题。

二哥

赞同来自:

如果你到达指针,那是 free//d, 他可以打破或不打破。 可以将此内存重新分配给程序的另一部分,然后您将损坏内存,

如果您设置指针 NULL, 然后在联系时,程序始终完成工作 segfault. 不再,有时它有效", 不再,失败不可预测". 调试更容易。

涵秋

赞同来自:

站立的想法是停止释放指针的随机重用。

君笑尘

赞同来自:

从标准 ANSI C:


void free/void *ptr/;


免费功能导致空间
指定的 ptr 必须发布
即进一步提供
分配。 如果一个 ptr 是一个指针 null,
然后没有任何动作发生。 否则if.
该论点与标志不相对应
, 以前返回的功能 calloc ,
malloc 或者 realloc, 或者如果
该空间被释放
称呼 free 或者 realloc , 行为
绝对不是。

"the undefined behavior"- 它几乎总是一个程序失败。 为避免这种情况,您可以安全地重置指针 NULL. free// 本身,不能这样做,因为它只是一个指针,而不是指向指针的指针。 您还可以编写更安全的版本。 free//, 什么 NULLs 指针:


void safe_free/void** ptr/
{
free/*ptr/;
*ptr = NULL;
}

八刀丁二

赞同来自:

我发现这一点有助于,就像我的经历一样,当人们转向释放内存分配时,它几乎总是发生,因为他们有一些其他指针。 然后他与另一个个人标准的冲突进入,称为 "避免无用的障碍", 因此,我不这样做,因为我认为很少有帮助,使代码不太可读。

但 - 我不会建立一个变量 null, 如果指针不应该再次使用,但通常更高级别的设计给了我建立它的原因 null 反正。 例如,如果指针是类成员,并且我删除了它指示的内容 "contract", 如果您愿意,该类是此成员将在任何时间指示有效的内容,因此必须安装它 null 为此原因。 有点区别,但我认为很重要。

在 c++ 思考谁总是很重要

拥有

您分配一些内存时这些数据 /除非你使用智能指针,否则即使那么需要一些思考。/. 这个过程通常会导致指针通常是某个类的成员,通常您希望该类始终处于允许状态,以及最简单的方法是建立一个成员变量 NULL, 表明它现在没有表明。

一般模板是建立所有成员标志 NULL 在设计师并使析构函数调用 delete 对于您设计所说的数据的任何指示,

拥有

这个班 . 显然,在这种情况下,您必须建立指针 NULL, 当您删除某些东西时要指出您不先前使用任何数据。

所以,总结,是的,我经常安装指针 NULL 删除某些东西后,这是一个更广泛的设计和关于谁拥有数据的反映的一部分,而不是由于标准编码规则之后的盲目。 我在你的榜样中我不会这样做,因为我认为它没有任何好处,他补充道 "clutter", 在我的经验中,这是对错误和坏代码的负责,就像这样的事情一样。

莫问

赞同来自:

它 /也许/ 非常重要。 虽然你释放了内存,但程序的后期部分可以分配新的东西,这是在太空中的地面发生的新东西。 您的旧指针现在将指向允许的内存。 然后有人可能会使用指针,这将导致程序的无效状态。

如果你 NULL 从指针中,然后使用它的任何尝试都会导致机会 0x0 并且在那里失败,这很容易调试。 指向随机内存的随机指针很难调试。 显然,没有必要,但这就是为什么它包含在最佳实践的文件中。

莫问

赞同来自:

我最近在寻找答案后面临同样的问题。 我得出了这个结论:

这是最好的做法,你需要跟随她,让它成为所有人 /内置/ 系统。


free//

- 这是一个库函数,随着平台的变化而变化,因此您不应该指出将指针传递到此函数并发布内存后,将安装此指针 NULL. 这可能不是那种为平台实现的库。

所以总是去


free/ptr/;
ptr = NULL;

奔跑吧少年

赞同来自:

当您尝试避免以下方案时,此规则很有用:

1/ 您具有复杂的逻辑和内存管理的真正长的功能,并且您不希望在此函数稍后意外地重用指向远程内存的指针。

2/ 指针是具有相当复杂的行为的类成员变量,并且您不希望意外地将指针重用到其他功能中的远程内存。

在您的场景中,它没有很大的意义,但如果函数变长,则可能很重要。

您可能会争辩说安装它 NULL 实际上可以伪装逻辑错误,或者在你假设它是有效的情况下,你仍然落在 NULL, 所以没关系。

一般来说,我建议你安装它 NULL, 当你认为这是一个好主意时,当你认为这不值得的时候,不要担心。 相反,专注于编写短功能和开发的课程。

快网

赞同来自:

安装刚刚发布的指针 NULL 这不是强制性的,但是良好的做法。 因此 , 你可以避免 1/ 使用发布的指针 2/做了 towice

知食

赞同来自:

安装指针 NULL 旨在保护 agains 所谓的双重自由情况 free// 在此地址在此地址重新分发块的情况下,在同一地址呼叫多次访问。

双重自由导致不确定的行为 - 通常损坏堆或计划立即失败。 称呼 free// 对于指针 NULL 没有任何东西,因此保证安全。

因此,如果您现在不确定指针立即离开行动面积,最好是 free//, 将此指针设置为 NULL, 即使是 free// 再次调用,现在调用指针 NULL 避免了不确定的行为。

卫东

赞同来自:

有两个原因:

避免双重解放失败

发布


https://coderoad.ru/1879168/
.

c中最常见的错误是 double
free. 主要是你做的事情
tot


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


它结束得非常糟糕, OS 试
释放一些释放的内存和
一般来说,它 segfault. 因此,好的
练习设定值
NULL

, 那么你
如果你真的可以做测试并检查
需要释放这个记忆


if/foobar != NULL/{
free/foobar/;
}


还应该指出的是
free/NULL/

什么都不会,所以你不需要
写 if statement. 一世
事实上,不是大师 OS, 但我甚至很漂亮
现在大部分 OSes 会崩溃 double
free.

这也是所有的主要原因
垃圾收集的语言
/Java, dotnet/ 他不喜欢他没有
这是这个问题,也没有
有必要离开开发人员管理
作为一个整体的记忆。

避免使用已经解放的指针

作者:


https://coderoad.ru/1025589/
.

将未使用的指针安装到NULL
保护风格保护
切割虫标志。 如果访问挂
指针在释放后执行,
您可以读取或覆盖随机
记忆。 何时参考指针
null 你最终会失败
系统立即通知您
错误是。

对于局部变量可能是
如果是这样的话很有意义
"obvious" 指针不再是
解放后可用,所以
这种风格更适合
数据成员和全局变量。 甚至
对于局部变量,它可以是一个很好的解决方案。
如果功能持续存在
释放内存后。

要完成风格,您还必须
初始化指针 NULL, 前
他们将被分配真实
指针的值。

郭文康

赞同来自:

要添加到别人说的内容,使用指针的一个好方法始终检查是否是允许指针。 有点:


if/ptr/
ptr->CallSomeMethod//;


显式标记指针如 NULL 发布后允许您使用此类 C/C++.

卫东

赞同来自:

初始化所有指针可能更多的参数 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

可以覆盖各种无关的东西并导致丑陋的错误。 特别是如果编译器在调试模式下将局部变量初始化为零,但在打开优化之后不会使其成为不变。 因此,调试程序集不会显示任何错误迹象,而释放程序集随机爆炸......

董宝中

赞同来自:

这个想法是,如果你试图挑战指针 no-longer-valid 在他的解放后,你想要遭受艰苦的失败 /segfault/, 不是默默和神秘的。

不过要小心。 并非所有系统都会原因 segfault, 如果你正在改变 NULL. On /至少一些版本/ AIX, */int */0 == 0, 和 Solaris 有额外的兼容性 AIX "feature."

君笑尘

赞同来自:

到初始问题:
安装指针 NULL 在释放内容之后立即完整花费时间,只要代码符合所有要求,完全调试并且永远不会更改。 另一方面,保护 NULLing 被释放的指针,当有人在无意识地添加新的块代码时,可以非常有用 free//, 当源模块的设计不正确时,并且在错误的情况下 it-compiles-but-doesn't-do-what-I-want.

在任何系统中,都有一个无法实现的目标,使其比正确的事情更容易,以及不准确的测量的进入成本。 在 35 我们提供一套非常尖锐的,非常强大的工具,可以在合格的工作者手中创造许多东西,并在不正确的处理中涂抹各种隐喻伤害。 其中一些很难理解或正确使用。 而且自然不倾向于风险的人做出非理性的事情,例如检查指针意义 NULL, 在打电话之前 free 和他一起…

测量问题是,每当你试图将好的效果分开,更难以求困难,你就越有可能进行暧昧的测量。 如果目标是保持良好的做法,那么他们的一些暧昧却被扔在一起,实际上是坏事。 IF 你的目标是消除糟糕,那么含糊不清就可以留下来。 这两个目标,保持良好或消除明显差,它看起来截然不同,但通常有一个第三组既不是另一种,其中一些都是两者。

在联系质量部门之前,请尝试查看错误数据库以了解多久,如果有史以来,指针值无效导致要记录的问题。 如果要真正改变情况,请确定生产代码中最常见的问题,并提供三种方法来防止它。

二哥

赞同来自:

由于您有一个团队来确保质量,让我增加一个小点 QA. 一些自动化工具 QA 为了 C 将解放迹象标记为 "无用的目的
ptr

". 例如 PC-lint/FlexeLint 经过 Gimpel Software 他说
tst.c 8 Warning 438: Last value assigned to variable 'nPtr' /defined at line 5/ not used


有选择性交付消息的方法,因此您仍然可以满足所有要求 QA, 如果您的团队决定如此。

君笑尘

赞同来自:

始终建议声明指针变量

NULL

, 例如,


int *ptr = NULL;


认为

ptr

表示内存地址

0x1000

.
使用后
free/ptr/

, 始终希望重置指针变量以重新验证

NULL

.
例如:


free/ptr/;
ptr = NULL;


如果指针变量未被声明重新入住

NULL

, 她仍然继续指出同一个地址 /

0x1000

/, 调用此变量指针

挂指针

.
如果您定义另一个指针变量 /让我们说

q

/ 并动态地将地址分配给新指针,有机会采取相同的地址 /

0x1000

/ 新指针变量。 如果在这种情况下,您使用相同的指针 / ptr / 并将值更新到相同指针指定的地址 / ptr /, 然后程序将最终将该值记录到其指示的位置 q /只要 p 和 q 表示相同的地址 / 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.

帅驴

赞同来自:

简而言之,你不想要随机 /因为失误/ 访问您释放的地址。 因为当您豁免地址时,您允许在堆中允许此地址分配给其他应用程序。

但是,如果您没有安装指针 NULL 并且错误地,尝试取消指针的链接或更改此地址的值,您仍然可以无论如何都可以执行此操作。 但不是你逻辑上的事情要做。

为什么我仍然可以访问我释放的内存区域? 因为:您可能已经释放了内存,但指针变量仍包含有关堆的内存地址的信息。 因此,作为防御战略,请安装它 NULL.

要回复问题请先登录注册