[C]每个通过malloc动态分配的内存都需要通过free通过吗?

garyHost 2011-08-24 06:37:56
大家好,


#include <stdlib.h>

void main( void )
{
int *p = ( int * ) malloc( sizeof( int ) );

if ( NULL == p )
exit( -1 );

int *q = ( int * ) malloc( sizeof( int ) );
if ( NULL == q )
{
free( p ); /*释放已经分配成功的p对应的内存空间*/
exit( -2 );
}

int *r = ( int * ) malloc( sizeof( int ) );
if ( NULL == r )
{
free( p );
free( q ); /*释放已经分配成功的p,q对应的内存空间*/
exit( -3 );
}

/*other code lines*/

free( p );
free( q );
free( r );

return;
}


我的问题是:

是否每个通过malloc动态分配的内存都需要通过free逐个的进行释放?如果是这样的话,诸如上述代码体现的,如果代码中有较多的判断可能导致函数非正常终止,那么是否都需要按照上面的写法以防止内存泄漏?个人感觉这样写有些繁琐,是否有其他更好的处理方法?

望高人不惜赐教,谢谢啦。:)
...全文
316 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
乔巴好萌 2011-08-26
  • 打赏
  • 举报
回复
1) 可以做一个内存池 不用频繁的malloc和free 分配一次 然后自己管理 最后一起释放 保证不会有泄漏 缺点是内存池不容易实现 而且要考虑多线程的操作
2) try...catch能少写点代码就少写点吧 呵呵 要不维护那么多的malloc和free看着眼花
garyHost 2011-08-26
  • 打赏
  • 举报
回复
受益颇多,感谢各位。
赵4老师 2011-08-25
  • 打赏
  • 举报
回复
进程退出时操作系统会帮你释放。
所以只要你的程序不在一个循环中拼命malloc或new就行。
txzsp 2011-08-25
  • 打赏
  • 举报
回复
这一直是C语言的一个问题。
指针的灵活性和安全性始终是一对矛盾。
但无论如何肯定是要用free()函数的。
lazy_2010 2011-08-25
  • 打赏
  • 举报
回复
两个办法,
1、把当前函数中使用到的所有指针封装成一个数据结构,例如

typedef struct tagContext {
int *p;
int *q;
int *r;
}Context;

void initContext(Context *pContext) {
pContext->p = NULL;
pContext->q = NULL;
pContext->r = NULL;
}

void freeContext(Context *pContext) {
free(pContext->p);
free(pContext->q);
free(pContext->r);
}

// 把原先的函数修改成使用 Context
int mainProc(Context *pContext, ...)
{
pContext->p = (int *)malloc(xxx);
if (pContext->p == NULL)
return -1;
pContext->q = (int *)malloc(xxx);
if (pContext->q == NULL)
return -1;
pContext->r = (int *)malloc(xxx);
if (pContext->r == NULL)
return -1;
...
}

int main(...)
{
Context context;
initContext(&context);
int nRes = mainProc(&context, xxx);
freeContext(&context);
return nRes;
}


2、使用 do {} while(0);


int main(xxx)
{
int nRes = -1;
int *p = NULL;
int *q = NULL;
int *r = NULL;
do{
p = (int *)malloc(xxx);
if (p == NULL)
break;
q = (int *)malloc(xxx);
if (q == NULL)
break;
r = (int *)malloc(xxx);
if (r == NULL)
break;
...;
}while(0);
free(p);
free(q);
free(r);
return nRes;
}
elichen9 2011-08-25
  • 打赏
  • 举报
回复
其实GOTO在很多情况下还是很有用的,书上说的是尽量少用GOTO,并非说不能用GOTO
zsc_ericluo 2011-08-25
  • 打赏
  • 举报
回复
还没怎么写代码,围观学习!
zw1270644192 2011-08-25
  • 打赏
  • 举报
回复
路过学习
wintree 2011-08-25
  • 打赏
  • 举报
回复
malloc分配的内存在叫“堆内存”,是动态分配的,即需要的时候就可以用malloc一个,不需要预先分配。用malloc分配的内存在c/c++中必须手动free释放,如果不释放,程序结束的时候可能会释放,也可能不释放。java中用new分配的内存和malloc效果相同,动态分配(堆内存),但是java可以不手动释放。系统自动回收。
AnYidan 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 qq120848369 的回复:]
高效的办法:凡是内存分配失败后,直接goto 函数末尾的err:位置,逐一释放各非空指针。
前提:所有指针初始化NULL


其他办法都避免不了你这个重复代码的写法。
[/Quote]

释放后将指针指向NULL, 可重复释放
honbaa 2011-08-24
  • 打赏
  • 举报
回复
malloc分配的内存在叫“堆内存”,是动态分配的,即需要的时候就可以用malloc一个,不需要预先分配。用malloc分配的内存在c/c++中必须手动free释放,如果不释放,程序结束的时候可能会释放,也可能不释放。java中用new分配的内存和malloc效果相同,动态分配(堆内存),但是java可以不手动释放。系统自动回收。
jackyjkchen 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 bokutake 的回复:]

VC里的话,C语言可以使用__try、__except、__finally这样的结构,比goto要优雅多了。
注意这个应该是VC.NET之后支持的,VC6可能不支持。

http://msdn.microsoft.com/en-US/library/zazxh1a9(v=VS.90).aspx
http://msdn.microsoft.com/en-us/library/yb3kz60……
[/Quote]
结构化异常,其实就是把c++的异常思想backport到C里了
辰岡墨竹 2011-08-24
  • 打赏
  • 举报
回复
VC里的话,C语言可以使用__try、__except、__finally这样的结构,比goto要优雅多了。
注意这个应该是VC.NET之后支持的,VC6可能不支持。

http://msdn.microsoft.com/en-US/library/zazxh1a9(v=VS.90).aspx
http://msdn.microsoft.com/en-us/library/yb3kz605(v=VS.90).aspx
jackyjkchen 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 icemornings 的回复:]

引用 4 楼 garyhost 的回复:

@qq120848369

呵呵,受教,的确是一种减少重复代码的方式。

不过看书上说goto会使程序结构混乱。

初学者,勿怪:)

书上说goto会使程序结构混乱是因为担心有个别菜鸟用goto跳来跳去。
goto如果只跳向一个方向,还会混乱么?如果你的循环层次非常多,你不用goto你得一层一层地跳出,
这些场合就可以使用go……
[/Quote]
++
不过我绝不会在程序里出现超过两层的循环
jackyjkchen 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 qq120848369 的回复:]

高效的办法:凡是内存分配失败后,直接goto 函数末尾的err:位置,逐一释放各非空指针。
前提:所有指针初始化NULL


其他办法都避免不了你这个重复代码的写法。
[/Quote]
++
goto最有用的用法,我的程序里都会出现,往往要给菜鸟们解释半天为什么我写的和书上说的不一样……
icemornings 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 zmlovelx 的回复:]

也可以把每个指针malloc后依次压栈,或者存入数组.
一旦有一个失败,就依次出栈, 一个循环free掉.
[/Quote]
照大神的方法写了个代码:

#include <stdio.h>
#include <stdlib.h>

/* 指针栈 */
enum {MAX_PTR = 100};
int *ptr_stack[MAX_PTR] = {0};
int top = -1;

/* 栈的操作 */
#define POP() ptr_stack[top--]
#define PUSH(ptr) ptr_stack[++top] = ptr
#define EMPTY() (top < 0)

int exit_code(int code);

int main(int argc, char **argv)
{
int *p = NULL, *q = NULL, *r = NULL;

if (NULL == (p = (int *)malloc(10)))
return exit_code(-1);

PUSH(p);

if (NULL == (q = (int *)malloc(20)))
return exit_code(-2);
PUSH(q);

if (NULL == (r = (int *)malloc(30)))
return exit_code(-3);
PUSH(r);

/* 做自己该做的事情 */

/* 结束 */
printf("OK\n");
return exit_code(0);
}

int exit_code(int code)
{
while (!EMPTY())
free(POP());
return code;
}

发现这样做有个问题,就是不能中途释放某个指针所指内容……
能不能这么做:
申请成功的指针放到一个链表中,如果中途释放的话就把指针从链表中取下来。
最后释放内存的时候按照链表中的指针释放。
这样会不会比较好。
icemornings 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 garyhost 的回复:]

@qq120848369

呵呵,受教,的确是一种减少重复代码的方式。

不过看书上说goto会使程序结构混乱。

初学者,勿怪:)
[/Quote]
书上说goto会使程序结构混乱是因为担心有个别菜鸟用goto跳来跳去。
goto如果只跳向一个方向,还会混乱么?如果你的循环层次非常多,你不用goto你得一层一层地跳出,
这些场合就可以使用goto。
-------------------
固守成见都是不好的,书呆子更是不好。
icemornings 2011-08-24
  • 打赏
  • 举报
回复
丢个代码,自己常这么写……

#include <stdio.h>
#include <stdlib.h>

/* 释放内存 */
#define SAFE_FREE(p_buf) \
do \
{ \
free((p_buf)); \
(p_buf) = NULL; \
} while (0)

int main(int argc, char **argv)
{
int *p, *q, *r;
int exit_code = 0;

/* 初始化为NULL */
p = q = r = NULL;

if (NULL == (p = (int *)malloc(10)))
{
exit_code = -1;
goto end_proc;
}

if (NULL == (q = (int *)malloc(20)))
{
exit_code = -2;
goto end_proc;
}

if (NULL == (r = (int *)malloc(30)))
{
exit_code = -3;
goto end_proc;
}

/* 分配成功,做自己该做的事 */
/* 如果其中有释放空间的代码,请使用SAFE_FREE() */
SAFE_FREE(q);

/* 清理并返回 */
end_proc:
SAFE_FREE(r);
SAFE_FREE(q);
SAFE_FREE(p);
return exit_code;
}

帅得不敢出门 2011-08-24
  • 打赏
  • 举报
回复
也可以把每个指针malloc后依次压栈,或者存入数组.
一旦有一个失败,就依次出栈, 一个循环free掉.
garyHost 2011-08-24
  • 打赏
  • 举报
回复
@qq120848369

呵呵,受教,的确是一种减少重复代码的方式。

不过看书上说goto会使程序结构混乱。

初学者,勿怪:)
加载更多回复(3)

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧