首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

关于 free() 函数用法的若干疑点

2013-09-21 
关于 free() 函数用法的若干疑问《C语言参考手册》中关于 free() 函数有如下描述。(1)free() 函数的原型void

关于 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
------解决方案--------------------


引用:
Quote: 引用:

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)来判别。
[解决办法]
完整的套路其实应该是这样的:

int * p = NULL;
p = (int *)malloc(sizeof(int));
if (!p)
  goto error;

... // 省略代码若干,也许有其他资源的分配以及goto error

error:
if (p)
{
  free(p);
  p = NULL;
}

[解决办法]
引用:
Quote: 引用:

Quote: 引用:

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.)
[解决办法]
引用:
Quote: 引用:

Quote: 引用:

Quote: 引用:

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.)

不解释,呵呵
[解决办法]
引用:
Quote: 引用:

Quote: 引用:

Quote: 引用:

Quote: 引用:

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函数有用?
[解决办法]
是的 
做free(ptr)之前 对ptr做NULL比较是完全多余的做法

直接free(ptr)就可以

[解决办法]



引用:
Quote: 引用:

Quote: 引用:

Quote: 引用:

Quote: 引用:

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。

一个小小的问题,经过与大家的交流,学到很多背后的知识,或者说在使用时应该注意的问题。这就是为什么会提出并不断向大家学习的原因。

真的学到不少知识,谢谢大家的回答。

你这样写只会增加阅读代码的复杂性,某些代码之所以对ptr非空判断,是为了防止在某些系统对free(NULL)而引起crash,如PalmOS,3BSD。讨论到此为止

相链接:http://www.winehq.org/pipermail/wine-patches/2006-October/031544.html

[解决办法]
一个良好的代码。

1)符合标准。
2)对某些,不执行标准的编译器(或者这个编译器很古老),也能很好的工作。

如果,你只用最新的,符合最新标准的编译器,只要你的代码,和标准不冲突
而且,没有利用一些,标准规定的未定义行为,那么,就是比较好的代码了。

其他方面,就是代码规范的问题了。

热点排行