对于C语言函数内部的动态分配内存的处理???(300分)

  • 主题发起人 主题发起人 laline
  • 开始时间 开始时间
L

laline

Unregistered / Unconfirmed
GUEST, unregistred user!
C语言中对于返回值是CHAR * 的函数,常要动态分配内存,
比如:
char * p;
char * aaa()
{char * z;
z =(char *) malloc(100);
strcpy(z,"hello");
return z;
}
p = aaa();
free(p);
我的问题是对于这种内存是否需要在函数调用后自己手动释放内存,即free(p);是否必要,
如果不必要,难道函数结束时自动释放,如果自动释放,那么 “hello”这个字符串内容
放在哪里,如果不必要是不是程序结束后系统会自动释放?
另外,在WIN2K下如果主动释放非本函数内分配的会出现 “该内存不能为READ”的错误
而LINUX下不会,谁能解释一下???
 
肯定要自己手动释放.
 
如果是一些非动态分配变量则可以不要,如常用的变量AnsiString a,b等变量过程会自己
处理,如是编程员用了一些分配内存指令生成的则要手工处理
 
在Windows下,你手工申请的内存(malloc)是在远堆中分配的,你当然得自己释放,
LINUX我不清楚,但这是两个操作系统,其内存管理机制大不一样,可能LINUX的内存
管理机制更完美些吧...
 
对内存的管理都是一样的,程序创建的内存,一定要由程序来释放,否则会内存泄漏。
象你上面所描述的情况,如果不想自己释放内存,最后用static char z[100];这样系统
会帮你释放内存的。
 
我认为:
函数aaa()返回后,z将自动释放,p指向z曾经指的内存地址。
当p离开作用域后,p将自动释放,'Hello'成了内存中的垃圾。
如果有错,敬请高手指正
 
用Malloc动态分配内存后,必须用Free来释放。
 
呵呵,还好我看到了。
char * aaa()
{
char * z;
z =(char *) malloc(100);
strcpy(z,"hello");
return z;
}
这种写法是问题大大的。
z在进程的堆上分配,作用域在aaa中,函数返回时z所指向的内存
被系统解锁,这块内存变成可以再分配的,所以它的值是不确定的,
虽然接着有p = aaa()语句,之间似乎没有被打断,p指向的内存块应该还
是“hello”串。
但其中忽略了一个重要问题,就是window是抢占式操作系统。
因为线程是在汇编级别调度的,所以aaa返回时可能并不能马上
执行p = aaa(),而是被别的线程抢去了cpu时间,如这个线程要用堆,
很可能改写了z指向的内容。
以上情况发生几率不高,但windows程序却无论如何不能这样写,这是bug的产生源。
应该如何写呢?
当定义z时可以定义为静态的,
static char *z;
当p = aaa()后最好free(p)。
因为当进程死亡后,系统虽然会清除进程的堆空间,但如果aaa被反复调用
会造成运行时内存泄露,这样程序长时间运行性能会受影响。
关于window内核的一些细节问题是我们日常编程时应该小心注意的。
 
Malloc函数必须手动释放,不用想了.
 
如果能确定aaa只被调用一次,那么不用free也是可以的,
但这不是好的编程习惯。
可以看出xeen,hgtzy等还是初学者,编程还没有入门,
他们的回答是一种不负责任的表现。
 
C语言中对于返回值是CHAR * 的函数,常要动态分配内存,
比如:
char * p;
char * aaa()
{char * z;
z =(char *) malloc(100);
strcpy(z,"hello");
return z;
}
p = aaa();
free(p);
我的问题是对于这种内存是否需要在函数调用后自己手动释放内存,即free(p);是否必要,
如果不必要,难道函数结束时自动释放,如果自动释放,那么 “hello”这个字符串内容
放在哪里,如果不必要是不是程序结束后系统会自动释放?
另外,在WIN2K下如果主动释放非本函数内分配的会出现 “该内存不能为READ”的错误
而LINUX下不会,谁能解释一下???
我認為手動釋放有必要。函數結束時﹐不會自動釋放﹐不然函數aaa()都釋放了。系統結束﹐應該會釋放內存﹐不過要看什么操作系統。你說win2k下如果主动释放非本函数内分配的会出现 “该内存不能为READ”的错误﹐那這個函數是否會出現呢﹖如果會﹐程序可以這樣修改(見下)﹐LINUX沒有提示﹐未必沒有這樣的錯誤﹐也許只是沒有顯示給你看﹐就象windows系列的藍屏問題﹐系統可以改為黃屏﹐道理是一樣的。
char * p;
p = (char *)malloc(100);
char * aaa(char *z)
{
strcpy(z,"hello");
return z;
}
aaa(p);
free(p);
 
有malloc就得有free,有new就得有delete,这是c/c++的基本守则。。
 
c++推荐使用new/delete,不推荐使用malloc
另外“在WIN2K下如果主动释放非本函数内分配的会出现 “该内存不能为READ”的错误
”这个问题我可从来没碰过。连其他线程new的内存都可以delete之(自行同步)
 
to yyii_yyii and JamesBond_L:
看了二位的解释,我得出以下结论,不知道是否正确?
对于函数内分配的内存,比如z指向的内存,当函数结束时被操作系统释放为可重新被
分配使用的内存,虽然内存中的内容"hello"可能没有被主动清除,但并不代表它以后
不会被修改,所以当函数结束后,z指向的内存早已经成为野指针,即不用主动释放,
也不要使用它的内容(内容是不可靠的)。对于yyii_yyii提供的解决方法:
//static char *z;
//当p = aaa()后最好free(p)。
我表示怀疑,因为对于以上这个简单的程序其实不会出现“该内存不能为READ”的错误
我出现那个错误是在调用了其他函数库时出现的,所以我用那个例子又
做了一下实验,但是还是出现“该内存不能为READ”的错误,行不通,而在LINUX下编译
运行没有问题。
TO:PiPi 我用的是标准C,只是用cl编译器在WINDOWS平台下编译一下,所以不能用
new和delete运算符。
另:to yyii_yyi对于C语言提供的众多函数库里,有大量的返回指针型函数,除了
那些在传入参数中已经分配了空间,并且被返回的之外,也有不少需要在函数内部分配
空间的,比如getenv()函数,难道他们都是返回的静态数组?
对于各位回答的结论是不是就是:函数内部malloc出的内存不用手动释放!
下面我把那个出错的例子贴出来大家看看,如果能说出原因我再给300分
 
因为不能提问,只好借用此处一问:
斑竹:为什么Hebaisong的账号不能用???请给我一个解释!
是不是因为发了这个贴子?
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1937958
也没必要封号几个星期吧?????
 
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/timeb.h>
#define MAXLINE 100
#define INIFILENAME "LOCAL_INFORM.INI"
char *
strepl (char *str)
{
char *i;
char *retu = (char *) malloc ((strlen (str) + 1) * sizeof (char));
memset (retu, '/0', strlen (str) * sizeof (char));
i = retu;
while (*str)
{
if (*str == ' ' || *str == '/n')
{
str++;
continue;
}
*retu = *str;
retu++;
str++;
}
retu = i;
return retu;
}

char *
GetIniFile (char * filename, char * field, char * item, char * def)
/*文件名*/ /*域*/ /*项目*/ /*缺省值*/
{

FILE *fp;
int count = 0;
char buf[MAXLINE];
char sfield[MAXLINE];
char sitem[MAXLINE];
static char *tmp;
memset (buf, '/0', sizeof (buf));
fp = fopen (filename, "rb");

if (fp == NULL)
{

return def; /*输出文件打开错*/
}
sprintf (sfield, "[%s]", field);
sprintf (sitem, "%s=", item);
while (fgets (buf, MAXLINE, fp) != NULL)
{
if (count == 2)
break;
switch (count)
{
case 0:
if (!(tmp = strstr (strepl (buf), sfield)) &amp;&amp;
count == 0)
continue;
else
{
if (strepl (buf)[0] == '[')
count = 1;
continue;
}
case 1:
if (!(tmp = strstr (strepl (buf), sitem)) &amp;&amp;
count == 1)
continue;
else
{
count = 2;
break;
}
default:
continue;
}
}

if (count != 2)
return def;
fclose (fp);
return tmp + strlen (sitem);
}


char * aaa()
{
char * z;
z =(char *) malloc(100);
strcpy(z,"hello");
return z;
}
char * bbb()
{
char * c;
c=aaa();
return c;
}
main()
{
char * p;
char cJgdm[10];
memset(cJgdm,'/0',sizeof(cJgdm));
p = (char *)GetIniFile(INIFILENAME, "LOCAL", "jgdm", NULL);
if( p!=NULL )
strcpy(cJgdm,p);
else
return -1;
printf("本地机构代码是 %s/n",cJgdm);
free(p);

}
 
大家如果装了VC后,可以在控制台模式下
用cl *.c 编译后运行试试
文本文件 LOCAL_INFORM.INI 的内容是
[LOCAL]
jgdm=13001005
path=f:/
注意最后一行free(p);
加上它的时候就会出现“该内存不能为READ”的错误
而用p =aaa();free(p);就不会
 
建议楼主看看《windows核心编程》的第二、三部分,关于这个问题有很详细的说明。
进程、线程以及内存分配问题不仅和编译器有关,和操作系统也有关系。
 
多人接受答案了。
 
后退
顶部