free(ptr)其中ptr为NULL会损坏内存吗?


112

理论上我可以说

free(ptr);
free(ptr); 

这是内存损坏,因为我们要释放已经释放的内存。

但是如果

free(ptr);
ptr=NULL;
free(ptr); 

由于操作系统将以不确定的方式运行,因此我无法对此进行实际的理论分析。无论我在做什么,这是不是内存损坏?

释放NULL指针是否有效?


1
不确定C免费标准,但是在C ++中delete(NULL)是完全有效的,所以我想free(NULL)也应该是。
Priyank Bolia 09年

14
@Pryank:delete NULL在C ++中无效。delete可以应用于具体类型的空指针值,但不能应用于NULLdelete (int*) NULL是合法的,但不是delete NULL
AnT

所以这意味着如果一个指针指向NULL free不会执行任何操作,这意味着!!!!!! 每次在我们的编码中,如果要释放内存,都可以简单地将free(ptr)替换为ptr = NULL?
维杰2009年

3
否。如果ptr指向内存,而您没有调用free它,则内存将泄漏。将其设置为NULL只会失去对内存的处理能力并泄漏。如果ptr 碰巧是NULL,则调用free为空操作。
GManNickG

1
@benjamin:嗯?是什么让你得出这样的结论,你可以替换free(ptr)使用ptr = NULL。没有人这么说。
AnT

Answers:


224

7.20.3.2 free功能

概要

#include <stdlib.h> 
void free(void *ptr); 

描述

free函数导致由指向的空间ptr被释放,即可以用于进一步分配。如果ptr为空指针,则不执行任何操作。

ISO-IEC 9899

话虽如此,当您在野外查看不同的代码库时,您会发现人们有时会这样做:

if (ptr)
  free(ptr);

这是因为释放NULL指针后,某些C运行时(我肯定记得是PalmOS上的情况)会崩溃。

但是,如今,我相信可以安全地假设free(NULL)按照标准指示是nop。


29
不,ptr = NULL不能替代free(ptr),两者完全不同
Prasoon Saurav

7
NO,这意味着free(ptr)那里ptr是空没有副作用。但无论如何,使用malloc()calloc()必须随后使用释放的每个内存free()
Gregory Pakosz 09年

4
ptr = NULL可确保即使您不小心调用了free(ptr),您的程序也不会出现段错误。
Prasoon Saurav

2
请注意,尽管C标准说它是无操作的,但这并不意味着每个C库都像这样处理它。我见过free(NULL)崩溃,因此最好避免首先调用free。
Derick

6
@WereWolfBoy他的意思是free(NULL)通过NULL在致电之前测试指针来避免free()
Gregory Pakosz 2013年

22

C库的所有符合标准的版本都将free(NULL)视为无操作。

就是说,一次有一些免费版本会在free(NULL)上崩溃,这就是为什么您可能会看到一些防御性编程技术建议的原因:

if (ptr != NULL)
    free(ptr);

8
-1 [需要引用]。由于一些过时的传闻实现理论而改变代码风格是一个坏主意。
Tomas

41
@Tomas-我从不建议更改样式,我只是解释了为什么您仍然可以在某些样式中看到此建议。
R Samuel Klatchko 09年

5
@Tomas 3BSD(winehq.org/pipermail/wine-patches/2006-October/031544.html)和PalmOS两个(两个都是第二手)。
道格拉斯·里德

7
@Tomas:问题出在Unix 7版本。当我学习时,free(xyz)其中xyz == NULL是我所学习的机器(ICL Perq运行PNX,它基于版本7 Unix和一些System III附加功能)上造成即时灾难的原因。但是我已经很长时间没有那样编写代码了。
乔纳森·勒夫勒

2
Netware也因释放NULL而崩溃...(只是调试了崩溃...)
Calmarius


12

我记得在free(NULL)崩溃的PalmOS上工作。


4
有趣的是-导致第二个平台崩溃(在3BSD之后)。
道格拉斯·里德

2
如果我没记错的话,在Palm上不存在C标准库。而是有一个几乎不受支持的头文件,该头文件将标准库调用映射到Palm OS SDK。许多事情出乎意料。NULL与标准库相比,崩溃是Palm工具箱的主要运行差异之一。
史蒂芬·费舍尔

8
free(ptr);
ptr=NULL;
free(ptr);/*This is perfectly safe */

您可以安全地删除NULL指针。在这种情况下将不执行任何操作。换句话说,free()对NULL指针不起作用。


8

推荐用法:

free(ptr);
ptr = NULL;

看到:

man free

     The free() function deallocates the memory allocation pointed to by ptr.
     If ptr is a NULL pointer, no operation is performed.

将指针设置为NULL之后,free()您可以free()再次调用它,并且将不会执行任何操作。


3
这也有助于通过调试器发现段错误。显然,p = 0的p-> do()处的段错误是使用释放的指针的人。当您在调试器中看到p = 0xbfade12时不太明显:)
Neuro

6

free(NULL)在C delete (void *)0delete[] (void *)0C ++中都是完全合法的。

顺便说一句,释放内存两次通常会导致某种运行时错误,因此它不会破坏任何内容。


2
delete 0在C ++中不合法。delete明确需要一个指针类型的表达式。应用于delete类型化的null指针值是合法的,但不适用于0(也不适用于NULL)。
AnT

1
您不能删除void*任何一个:P它应该运行哪个析构函数?
GManNickG

1
@GMan:只要它是空指针,就可以删除void *
AnT

好,可以。我忘了我们只专门处理null。
GManNickG

通常不会破坏任何东西,但不能保证。ASLR使得这种情况不太可能发生,但仍然并非不可能:buf1=malloc(X); free(buf1);buf2=malloc(X);free(buf1); -如果不幸的话,buf2的地址与buf1完全相同,并且您不小心释放了buf1两次,因此在第二次释放buf1的过程中,您实际上是在无提示的情况下默默地释放了buf2。任何(严重)错误/崩溃/无论如何。(但是,下次尝试使用buf2时,您仍然可能会崩溃-如果在ASLR上运行,这种情况就不太可能发生)
hanshenrik

3

free(ptr)如果ptrNULL,则将C保存在C 中,但是,大多数人不知道的是NULL不必等于0。我有一个很好的老派例子:在C64的地址0上有一个IO端口。如果您使用C语言编写了一个访问该端口的程序,则需要一个值为0的指针。相应的C库必须在0和0之间进行区分NULL

亲切的问候。


有趣的事实让我惊讶。让我感到不得不去研究NULL指针问题/答案。
节肢动物,


-3

ptr指向某个内存位置,比方说0x100。

当您释放(ptr)时,基本上就是允许内存管理器使用0x100来进行其他活动或进程,简单来说就是资源的重新分配。

当您执行ptr = NULL时,就是将ptr指向新位置(不必担心NULL是什么)。这样做会丢失对0x100内存数据的跟踪。这就是内存泄漏。

因此,不建议在有效的ptr上使用ptr = NULL。

相反,您可以使用以下命令进行安全检查:

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

当free(ptr)的ptr已经指向NULL时,它不执行任何操作,因此这样做很安全。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.