|
|
1
269
将未使用的指针设置为空是一种防御风格,可以防止悬空指针错误。如果在释放悬空指针后访问该指针,则可以读取或覆盖随机内存。如果访问空指针,大多数系统都会立即崩溃,并立即告诉您错误是什么。 对于局部变量,如果指针在释放后“明显”不再被访问,那么它可能有点无意义,因此这种样式更适合于成员数据和全局变量。即使对于局部变量,如果函数在释放内存后继续运行,也可能是一种很好的方法。 要完成样式,还应在为指针赋值为真指针值之前将指针初始化为空。 |
|
|
2
36
将指针设置为
据说,设置一个指针
当然,当使用同一个指针对象作为参数
最后,如果您的代码专门设计为依赖
|
|
|
3
31
大多数响应都集中在防止双重释放上,但是将指针设置为空还有另一个好处。一旦释放一个指针,该内存就可以被另一个调用malloc重新分配。如果仍然有原始指针在身边,那么可能最终会出现一个bug,在释放并损坏其他变量后,您试图使用指针,然后您的程序进入未知状态,可能会发生各种错误(如果幸运,崩溃;如果不幸,数据损坏)。如果您在空闲后将指针设置为空,任何稍后通过该指针进行读/写的尝试都将导致segfault,这通常比随机内存损坏更可取。 出于这两个原因,最好在free()之后将指针设置为空。不过,这并不总是必要的。例如,如果指针变量在free()之后立即超出范围,则没有太多理由将其设置为空。 |
|
|
4
17
这被认为是避免重写内存的好方法。在上面的函数中,这是不必要的,但通常当它完成时,它会发现应用程序错误。 改为尝试类似的操作:
debug_版本允许您在调试代码中释放概要文件,但两者在功能上是相同的。 编辑 增加…如下文所述,谢谢。 |
|
|
5
7
如果您到达的指针是free()d,它可能会断开或不断开。内存可能会重新分配到程序的另一部分,然后内存会损坏, 如果您将指针设置为空,那么如果您访问它,程序总是崩溃,并出现一个segfault。不再,有时它工作,不再,以不可预知的方式崩溃。这样更容易调试。 |
|
|
6
7
将指针设置为
我可以看出你的论点:因为
很可能规则是在没有区分这两种情况的情况下声明的,因为自动执行规则要困难得多,更不用说开发人员遵循它了。把指针指向
|
|
|
7
7
C中最常见的bug是双自由。基本上你是这样做的
结果很糟糕,操作系统试图释放一些已经释放的内存,通常是segfault。所以好的做法是
还要注意的是
这也是为什么所有的垃圾收集语言(Java,DOTNET)都很自豪地没有这个问题,也不必让开发人员把内存管理作为一个整体。 |
|
8
6
其背后的想法是,停止意外重用释放的指针。 |
|
|
9
4
这实际上很重要。虽然您释放了内存,但是程序的后面部分可以分配一些新的东西,这些东西会发生在空间中。您的旧指针现在将指向一个有效的内存块。然后有可能有人会使用指针,从而导致无效的程序状态。 如果指针为空,那么任何使用它的尝试都将取消对0x0的引用,并在那里崩溃,这很容易调试。指向随机内存的随机指针很难调试。这显然是不必要的,但这就是为什么它出现在最佳实践文档中的原因。 |
|
|
10
4
根据ANSI C标准:
“未定义的行为”几乎总是程序崩溃。为了避免这种情况,可以安全地将指针重置为空。free()本身不能这样做,因为它只传递一个指针,而不是指向指针的指针。您还可以编写一个更安全的free()版本,该版本为空指针:
|
|
|
11
4
我发现这并没有什么帮助,就像我的经验一样,当人们访问一个释放的内存分配时,几乎总是因为他们在某个地方有另一个指向它的指针。然后它与另一个个人编码标准冲突,即“避免无用的混乱”,所以我不这样做,因为我认为它很少有帮助,使代码的可读性稍差。 但是,如果指针不应该再次使用,我不会将变量设置为空,但是更高级别的设计通常会给我一个理由将其设置为空。例如,如果指针是某个类的成员,并且我删除了它指向的内容,那么如果您喜欢该类的“约定”是该成员将随时指向某个有效的内容,因此必须为此将其设置为空。有点区别,但我认为很重要。 在C++中,重要的是始终在思考谁 拥有 当您分配一些内存时,这个数据(除非您使用智能指针,但甚至需要一些思考)。这个过程往往会导致指针通常是某个类的成员,通常您希望某个类始终处于有效状态,最简单的方法是将成员变量设置为空以指示它现在不指向任何对象。 一个常见的模式是将构造函数中的所有成员指针设置为空,并让析构函数对设计中所说的类的数据的任何指针调用delete。 拥有 .显然,在这种情况下,当您删除某些内容时,必须将指针设置为空,以表明您以前没有任何数据。 总而言之,是的,我经常在删除某个内容后将指针设置为空,但这是更大设计的一部分,并考虑谁拥有数据,而不是盲目地遵循编码标准规则。在您的示例中,我不会这样做,因为我认为这样做没有好处,而且它添加了“杂乱”,在我的经验中,这和此类事情一样对错误和坏代码负责。 |
|
|
12
4
最近我在寻找答案后遇到了同样的问题。我得出这个结论: 这是最佳实践,必须遵循这一点,使其在所有(嵌入式)系统上都可移植。
所以总是去
|
|
|
13
3
当您试图避免以下情况时,此规则非常有用: 1)您有一个非常长的函数,具有复杂的逻辑和内存管理,您不希望在函数的后面意外地重用指向已删除内存的指针。 2)指针是具有相当复杂行为的类的成员变量,您不希望在其他函数中意外地重用指向已删除内存的指针。 在您的场景中,这并没有什么意义,但是如果函数变长了,这可能很重要。 您可能会争辩说,将其设置为空可能会在以后掩盖逻辑错误,或者在假定它有效的情况下,您仍然会崩溃于空,所以这并不重要。 一般来说,如果你认为这是个好主意,我建议你把它设为空,如果你认为它不值得,我建议你不要麻烦。专注于编写简短的函数和设计良好的类。 |
|
|
14
2
另外,一个好的指针使用方法是始终检查它是否是有效的指针。类似:
显式地将指针标记为NULL在释放之后,允许在C/C++中使用这种类型。 |
|
|
15
2
这可能更像是一个初始化所有指向空值的指针的参数,但类似这样的错误可能是非常隐蔽的:
|
|
16
2
将刚刚释放的指针设置为空不是强制的,而是一个好的实践。这样,您就可以避免1)使用自由尖2)自由它拖缆 |
|
|
17
2
设置指向空值的指针是为了保护所谓的双空闲-当同一地址多次调用free()而不在该地址重新分配块时的情况。 双重空闲会导致未定义的行为-通常是堆损坏或程序立即崩溃。为空指针调用free()没有任何作用,因此保证是安全的。 因此,除非您现在确定指针立即离开作用域或在free()之后很快离开作用域,否则最好的做法是将该指针设置为空,这样即使再次调用free(),也会调用该指针,从而避免未定义的行为。 |
|
|
18
2
其思想是,如果在释放不再有效的指针后尝试取消对它的引用,那么您希望硬失败(segfault),而不是默默无闻地、神秘地失败。 但是…小心。如果取消对空值的引用,并非所有系统都会导致segfault。在(至少某些版本的)AIX上,*(int*)0==0,并且Solaris与此AIX“特性”具有可选的兼容性。 |
|
|
19
2
对于原始问题:
在释放内容后直接将指针设置为空是完全浪费时间的,前提是代码满足所有要求,已完全调试并且不会再修改。另一方面,如果有人在free()下面无意中添加了一个新的代码块,当原始模块的设计不正确时,以及在编译但不执行我想要的错误的情况下,防御性地取消已释放的指针可能非常有用。
|
|
|
20
2
有两个原因: 避免在双重释放时崩溃由书面 RageZ 在一个 duplicate question .
避免使用已释放的指针由书面 Martin v. Löwis 在一个 another answer .
|
|
|
21
1
既然你们有一个质量保证团队,让我补充一点关于QA的内容。一些针对C的自动化QA工具将释放指针的分配标记为“无用的分配给
有一些方法可以选择性地抑制消息,因此如果您的团队决定这样做,您仍然可以满足这两个QA需求。 |
|
|
22
1
始终建议使用 无效的 比如,
让我们说,
PTR
指向
0x1000
内存地址。
使用后
如果没有重新声明 无效的 ,指针变量仍继续指向同一地址( 0x1000 ,此指针变量称为 悬空指针 . 如果定义另一个指针变量(比如, Q )动态分配地址给新指针,就有可能获得相同的地址( 0x1000 )通过新的指针变量。如果在这种情况下,使用相同的指针( PTR )更新同一指针指向的地址值( PTR ,然后程序将写入一个值到 Q 指向(因为 磷 和 Q 指向同一地址( 0x1000 ) 例如
|
|
|
23
1
长话短说:你不想意外地(错误地)访问你释放的地址。因为,当释放地址时,您允许将堆中的地址分配给其他应用程序。 但是,如果不将指针设置为空,并且错误地尝试取消对指针的引用,或者更改该地址的值;您仍然可以这样做。但这不是你逻辑上想做的。 为什么我仍然可以访问我释放的内存位置?因为:您可能已经释放了内存,但是指针变量仍然有关于堆内存地址的信息。因此,作为防御策略,请将其设置为空。 |
|
|
MaPo · Linux,设置锁定ICMP_过滤器选项 1 年前 |
|
Doohyeon Won · 内联函数上的奇怪现象?[关闭] 1 年前 |
|
|
Bobby · 复合字面值总是左值吗? 1 年前 |
|
9-Pin · C: 嵌套结构的堆栈内存分配 1 年前 |