关于 free() 函数用法的若干疑问
《C语言参考手册》中关于 free() 函数有如下描述。
(1)free() 函数的原型
void free(void *ptr);
(2)free 函数对以前由 malloc、calloc、或 realloc 所分配的一块内存区域进行销毁。free 函数的参数必须是与某个内存分配函数的返回值相同的指针。如果它的参数是个 null 指针,则调用这个函数不会产生任何效果。
既然“如果它的参数是个 null 指针,则调用这个函数不会产生任何效果。”那么为什么一般写成 if(ptr != NULL) free(ptr),而不是直接 free(ptr) 呢?应该不仅是一个书面方面的良好编程风格吧?! free()?函数用法 内存分配 c语言 编程
[解决办法]
C++ reference 上是这么说的:
Prototype
#include <stdlib.h>
void free(void *ptr);
Description
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs.
最后一句句子回答了你的问题。
如果ptr是个null指针,free不会做任何操作。
但是在某些系统上free(NULL)会报错,或者造成程序的崩溃。
所以需要在前面加一个判定。
如果你确定你所写的代码在一个系统上运行,而且这个系统的free(NULL)不会出问题,那么你就可以不需要这个判定了。
[解决办法]
7.22.3.3 Thefreefunction
Synopsis
1 #include <stdlib.h>
void free(void *ptr);
Description
2 The free function causes the space pointed to by ptrto be deallocated, that is, made
available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if
the argument does not match a pointer earlier returned by a memory management
function, or if the space has been deallocated by a call to free or realloc, the
behavior is undefined.
Returns
3 The free function returns no value.
以上语句来源于ISO/IEC 9899:201x,348页。在C标准里,它返回空值,正如上文中说,如果ptr指向的空间已经通过调用free或realloc释放了,再次调用free函数的行为是未定义的
[解决办法]
如果已经为NULL的话,就不在系统调用阿!
优化而已!free是一个系统函数,调用很好资源的,
[解决办法]
如果是null,我从来直接free,可以简化代码。
[解决办法]
free(NULL)确实没有任何作用。
但下面的代码可不是没用。
if(p!=NULL)
{
free(p);
p=NULL;
}
不是为了好看。
因为:如果一个软件很大的时候,你可能不知道p是否分配过。因为分配内存的行为可能不是你引起的,但释放p又是你的责任,你该怎么办。上面代码其实是为了解决这个问题。
举个例子:
你写了一个模块,这个模块提共三个函数:
//module.h
void Init();
void Use();
void release();
///module.c
int *p;
void Init()
{
p=NULL;
}
void Use()
{
p=(int*)alloc(sizeof(int));
}
void release()
{
if( p!=NULL)
{
free(p);
}
}
请注意:你写的这个模块提供了三个功能(init, use, release); 但这个模块都是给别人用的。你的release被调用时你并不知道他是否调用过use(),So, 就又了上面你的问题。
Ok.你应该明白了:)
[解决办法]
多说一句,free后指针不会变为NULL,也不可能变成NULL, 因为free不能改变参数的值。
[解决办法]
if(ptr != NULL) free(ptr);的前面应该是
free(ptr); ptr=NULL;
重复释放是会产生问题的
[解决办法]
不同意这种写法,加不加if的判定,对free函数无效,如果要说防止再次free,最好就是调用free后,令ptr=NULL
[解决办法]
free(NULL)确实没有任何作用。
但下面的代码可不是没用。
if(p!=NULL)
{
free(p);
p=NULL;
}
不是为了好看。
因为:如果一个软件很大的时候,你可能不知道p是否分配过。因为分配内存的行为可能不是你引起的,但释放p又是你的责任,你该怎么办。上面代码其实是为了解决这个问题。
举个例子:
你写了一个模块,这个模块提共三个函数:
//module.h
void Init();
void Use();
void release();
///module.c
int *p;
void Init()
{
p=NULL;
}
void Use()
{
p=(int*)alloc(sizeof(int));
}
void release()
{
if( p!=NULL)
{
free(p);
}
}
请注意:你写的这个模块提供了三个功能(init, use, release); 但这个模块都是给别人用的。你的release被调用时你并不知道他是否调用过use(),So, 就又了上面你的问题。
Ok.你应该明白了:)
不同意这种写法,加不加if的判定,对free函数无效,如果要说防止再次free,最好就是调用free后,令ptr=NULL
你说得对,应该写成
void release()
{
if( p!=NULL)
{
free(p);
p=NULL;
}
}
我是为了告诉他为什么要这么做,没有深究,事实上,我所做的工作中基本上经常要这么写,而之所以这么写就是我上面说的原因:你不确定一个指针是否分配过,用if(p!=NULL)来判别。
free(NULL)确实没有任何作用。
但下面的代码可不是没用。
if(p!=NULL)
{
free(p);
p=NULL;
}
不是为了好看。
因为:如果一个软件很大的时候,你可能不知道p是否分配过。因为分配内存的行为可能不是你引起的,但释放p又是你的责任,你该怎么办。上面代码其实是为了解决这个问题。
举个例子:
你写了一个模块,这个模块提共三个函数:
//module.h
void Init();
void Use();
void release();
///module.c
int *p;
void Init()
{
p=NULL;
}
void Use()
{
p=(int*)alloc(sizeof(int));
}
void release()
{
if( p!=NULL)
{
free(p);
}
}
请注意:你写的这个模块提供了三个功能(init, use, release); 但这个模块都是给别人用的。你的release被调用时你并不知道他是否调用过use(),So, 就又了上面你的问题。
Ok.你应该明白了:)
不同意这种写法,加不加if的判定,对free函数无效,如果要说防止再次free,最好就是调用free后,令ptr=NULL
你说得对,应该写成
void release()
{
if( p!=NULL)
{
free(p);
p=NULL;
}
}
我是为了告诉他为什么要这么做,没有深究,事实上,我所做的工作中基本上经常要这么写,而之所以这么写就是我上面说的原因:你不确定一个指针是否分配过,用if(p!=NULL)来判别。
检查指针是否为空,多此一举。(If ptr is a null pointer, no action occurs.)
free(NULL)确实没有任何作用。
但下面的代码可不是没用。
if(p!=NULL)
{
free(p);
p=NULL;
}
不是为了好看。
因为:如果一个软件很大的时候,你可能不知道p是否分配过。因为分配内存的行为可能不是你引起的,但释放p又是你的责任,你该怎么办。上面代码其实是为了解决这个问题。
举个例子:
你写了一个模块,这个模块提共三个函数:
//module.h
void Init();
void Use();
void release();
///module.c
int *p;
void Init()
{
p=NULL;
}
void Use()
{
p=(int*)alloc(sizeof(int));
}
void release()
{
if( p!=NULL)
{
free(p);
}
}
请注意:你写的这个模块提供了三个功能(init, use, release); 但这个模块都是给别人用的。你的release被调用时你并不知道他是否调用过use(),So, 就又了上面你的问题。
Ok.你应该明白了:)
不同意这种写法,加不加if的判定,对free函数无效,如果要说防止再次free,最好就是调用free后,令ptr=NULL
你说得对,应该写成
void release()
{
if( p!=NULL)
{
free(p);
p=NULL;
}
}
我是为了告诉他为什么要这么做,没有深究,事实上,我所做的工作中基本上经常要这么写,而之所以这么写就是我上面说的原因:你不确定一个指针是否分配过,用if(p!=NULL)来判别。
检查指针是否为空,多此一举。(If ptr is a null pointer, no action occurs.)
不解释,呵呵
free(NULL)确实没有任何作用。
但下面的代码可不是没用。
if(p!=NULL)
{
free(p);
p=NULL;
}
不是为了好看。
因为:如果一个软件很大的时候,你可能不知道p是否分配过。因为分配内存的行为可能不是你引起的,但释放p又是你的责任,你该怎么办。上面代码其实是为了解决这个问题。
举个例子:
你写了一个模块,这个模块提共三个函数:
//module.h
void Init();
void Use();
void release();
///module.c
int *p;
void Init()
{
p=NULL;
}
void Use()
{
p=(int*)alloc(sizeof(int));
}
void release()
{
if( p!=NULL)
{
free(p);
}
}
请注意:你写的这个模块提供了三个功能(init, use, release); 但这个模块都是给别人用的。你的release被调用时你并不知道他是否调用过use(),So, 就又了上面你的问题。
Ok.你应该明白了:)
不同意这种写法,加不加if的判定,对free函数无效,如果要说防止再次free,最好就是调用free后,令ptr=NULL
你说得对,应该写成
void release()
{
if( p!=NULL)
{
free(p);
p=NULL;
}
}
我是为了告诉他为什么要这么做,没有深究,事实上,我所做的工作中基本上经常要这么写,而之所以这么写就是我上面说的原因:你不确定一个指针是否分配过,用if(p!=NULL)来判别。
检查指针是否为空,多此一举。(If ptr is a null pointer, no action occurs.)
您的答复,直接回到了我的问题本身。本来经过大家的讨论,略有些明白,但是经您这么一说,就“检查指针是否为空,多此一举。(If ptr is a null pointer, no action occurs.)”我也持相同看法。
但是,我觉得写成 if(!ptr) {fre(ptr), ptr =NULL} 这种写法是比较好的编程风格,能够避免不少的很难察觉的 BUG。
一个小小的问题,经过与大家的交流,学到很多背后的知识,或者说在使用时应该注意的问题。这就是为什么会提出并不断向大家学习的原因。
真的学到不少知识,谢谢大家的回答。