|
nico |
发表于: 2001/12/20 09:34am
|
我也不太清楚,不过你试试下面这条语句: return &tmpstr; 或者写成 return &tmpstr[0]; |
| |
|
taodale |
发表于: 2001/12/20 09:50am
|
如果你学过编译原理的话,对这个问题就会很清楚了。 你在函数里所定义的一个变量是临时变量,如char tmpstr[255]; 它仅在函数的生存期内有效。临时变量在函数被调用的时候分配所需的存储空间,在函数返回以后,这块空间会被系统收回派其它用场,所以返回它没有任何意义。 正确的用法是: char * getstr(){ char* tmpstr; tmpstr=(char*) malloc(255); strcpy(tmpstr,"------"); return tmpstr; }
|
| |
|
nico |
发表于: 2001/12/20 10:25am
|
| 楼上高水平,我很佩服,多谢了! |
| |
|
_cod_aas |
发表于: 2001/12/20 04:41pm
|
1.怎样才能释放你申请的空间??? 在主函数中调用free()?? but how??? |
| |
|
nico |
发表于: 2001/12/20 06:48pm
|
| 哈哈!这个问题问得好!如果按taodale的说法,就必须在函数中回收空间了。因为在函数之外的地方是没有这个tmpstr的。 |
| |
|
Sinbad |
发表于: 2001/12/21 01:32pm
|
char *p; p=getstr(); { do something using p } free(p); |
| |
|
lylizm |
发表于: 2001/12/21 03:14pm
|
以下代码在sco下编译通过,结果正确。 #include <stdio.h> int main(int argc,char **argv) { char *getstr(); char teststr[255]; strcpy(teststr,getstr()); printf("test [%s]\n",teststr); exit(0); } char * getstr(){ char tmpstr[255]; strcpy(tmpstr,"Hello World!"); return tmpstr; } 运行显示 test [Hello World!]
|
| |
|
_cod_aas |
发表于: 2001/12/21 05:21pm
|
我觉得Sinbad的做法不可取, 不过,我也不知道对不对。 那位高手知道的分析一下。 |
| |
|
nico |
发表于: 2001/12/23 01:40pm
|
include<stdio.h> char * getstr() { char tmpstr[255]; strcpy(tmpstr,"------"); return tmpstr; }main() { printf("%s\n",getstr()); } 本程序在tc2.0下调试通过。
|
| |
|
fzheng |
发表于: 2001/12/23 03:46pm
|
nice的程序有一点问题,在编译的时候会有warning: pointer to local 'tmpstr' is an illegal value. 其实,把程序改一下,就会发现错误。 #include <stdio.h>char * getstr() { char tmpstr[255]; strcpy(tmpstr,"------"); return tmpstr; } void anther() { char test[255]; strcpy(test,"this is a test"); } int main() { char *p; p=getstr(); anther(); printf("%s\n",p); return 0; } 结果是this is a test.堆栈中的数据被改变了。 |
| |
|
redwoods |
发表于: 2001/12/24 04:48pm
|
cod aas,你可不可以解释一下,为什么Sinbad的做法不可取。或者有什么好的办法可以解决这个问题。 我看着Sinbad的方法好像是对的。当然,我是个菜鸟,也不知道究竟对不对,而起现在出差在外,也没有办法试。 |
| |
|
nico |
发表于: 2001/12/25 10:41am
|
free()仅能释放malloc()申请的空间有关,这一点我在自己家的机器上试过了。 我上面的程序是对的,编译用的是tc2.0, 在win98的dos窗口下通过的,并没有warning。
|
| |
|
flyfish |
发表于: 2001/12/25 12:39pm
|
我想Sinbad的用法是安全的, 原因就是taodale 的高论。 |
| |
|
redwoods |
发表于: 2001/12/25 01:40pm
|
nico,你能不能查一下malloc()分配的空间用free()释放的时候有什么要求没有,是不是超出了分配的函数的生存期就不能释放了? 我想如果free()能在函数外释放内存,那还是Sinbad的方法安全。原因见fzheng的程序。 但是还有一个问题,就是如果free()的释放不受限制,那重载的变量该怎么处理? 比如: void test(void) { char * teststr; teststr=(char *)malloc(200); //do something,but not free teststr return; } int main(int argc,char **argv) { char *teststr; test(); teststr=(char*) malloc(255); //do something... free(teststr) ; exit(0) } 这会怎么样呢? |
| |
|
alonemelive |
发表于: 2001/12/25 08:44pm
|
| 为什么不把字符串指针作为参数传进函数呢??? |
| |
|
lchsh |
发表于: 2001/12/26 03:36pm
|
| 楼上的朋友,你的变量根本就是两个变量,没有重载。 |
| |
|
nico |
发表于: 2001/12/29 11:08am
|
[quote] nico,你能不能查一下malloc()分配的空间用free()释放的时候有什么要求没有,是不是超出了分配的函数的生存期就不能释放了? 我想如果free()能在函数外释放内存,那还是Sinbad的方法安全。原因见fzheng的程序。 但是还有一个问题,就是如果free()的释放不受限制,那重载的变量该怎么处理? 比如: void test(void) { char * teststr; teststr=(char *)malloc(200); //do something,but not free teststr return; } int main(int argc,char **argv) { char *teststr; test(); teststr=(char*) malloc(255); //do something... free(teststr) ; exit(0) } 这会怎么样呢? [/quote]free()仅释放main()中申请的空间。 但如果你试一下的话会发现在主函数中可以用函数test()中的teststr,也就是说free()掉main()中的teststr后,再次调用teststr后可以打出它的值。这是因为你设了两个相同的变量。不过,具体为什么会出现这种现象,用taodale的原理无法解释。我也不懂。 |
| |
|
fanyan1999 |
发表于: 2001/12/29 11:39am
|
我建议把程序改成这样: void getstr(char *tmpstr){ strcpy(tmpstr,"------"); } 在函数中返回字符串的方法不安全,因为函数结束时为该函数分配的内存都会被释放掉。fzheng的话很有道理。佩服佩服!!! |
| |
|
alai |
发表于: 2002/08/10 10:17am
|
| 这确是一个简单的问题,没有一个标准答案,Sinbad的方法也是对的,但更通常的做法是将tmpstr定义为静态的,这样它的内存不会在getstr()退出时被释放,也不需要在外面用free()释放,不过第二次调用getstr()会覆盖前次的返回值。这种方法是在许多标准C函数中被使用。 char * getstr(){ static char tmpstr[255]; strcpy(tmpstr,"------"); return tmpstr; }
|
| |
|
netstorm |
发表于: 2002/08/10 11:42am
|
[quote][b]下面引用由[u]lylizm[/u]在 [i]2001/12/21 03:14pm[/i] 发表的内容:[/b] 以下代码在sco下编译通过,结果正确。 以下代码在sco下编译通过,结果正确。 #include <stdio.h> int main(int argc,char **argv) { char *getstr(); char teststr[255]; strcpy(teststr,getstr()); printf("test [%s]\n",teststr); exit(0); } char * getstr(){ char tmpstr[255]; strcpy(tmpstr,"Hello World!"); return tmpstr; } 运行显示 test [Hello World!] [/quote]把 char tmpstr[255] 改成 char tmpstr[13],运行你的程序会出什么问题?? 如果定义成 static char tmpstr[13]呢?? :) |
| |
|
aegis |
发表于: 2002/08/10 12:09pm
|
nico 你的程序有问题,不能保证正确性 free () 能释放 malloc () 得到的内存。getstr () 函数不知是不是标准函数 我一般这样使用 c++:char * p = new char [ 255 ]; /* do some worke with p */ delete p; c: char * p; if ( null == (p = malloc ( 255 )) ) return ErrorNoMem; /* do some work with p */ free ( * p ); free () 可以在任何函数中使用,不必和 malloc 在同一作用域 但要注意 指针变量 的作用域问题; |
| |
|
flw |
发表于: 2002/08/12 09:06pm
|
我认为诸位的方法都不好.其实还有一种方法,那就是将 char tmpstr[255]; 声明写做: static char tmpstr[255]; 即可.不过这样将加长"静态存储区"的长度, 所以更科学的方法应该是将函数声明改成 char *getstr( char *tmpstr ); 即 tmpstr 由形式参数传入, 至于其空间嘛, 就不是 getstr 的责任了, 完全可以由外部分配. 另外我点评一下 taodale 的做法: 这样做虽然可以,但是习惯不好,降低了函数模块的"内聚性",谁上的厕所谁就冲马桶嘛! 另外, lylizm 的做法依赖于编译器, 本来嘛, 局部变量是存在于堆栈中的,那么对它的指针引用在堆栈不发生变化的前提下应该不会有问题, 但是,这不是 C 的语法所要求的, 所以并不可行/可靠, 换句话说, 这样做有三种结果: 1. 编译不能通过(因为编译器要求太严), 2, 内容不正确(原因比较复杂), 3, 正确. 事实上, 我在 SCO Unix 5.05 下就发现有这样的情况: (参见 lylizm 的例子) 在函数外部输出的内容为: [Hello World] 注意, 丢失了最后一个字符, 我曾经把 "电话银行" 中客户输入的密码就丢失了一位, 最后才查出是这个原因. 总之, 1,当 tmpstr 较短时, 宜采用类似 static char tmpstr[6]; 的写法; 2, 当 tmpstr 较长时, 宜采用外部分配, 外部回收, getstr() 处理指针的方法.
|
| |
|
flw |
发表于: 2002/08/12 09:13pm
|
| 不好意思, 我发上面这个帖子的时候没有看见第二页上各位大侠的帖子.所以有些话不太得体. |
| |
|
badeager |
发表于: 2002/08/31 01:19pm
|
#include <stdio.h> char *getstr(char *tmpstr) { // char tmpstr[255]; strcpy(tmpstr,"------"); return tmpstr; } int main() { char *p; p = (char *)malloc(255); p=getstr(p);printf("%s\n",p); return 0; } |
| |
|
sonice |
发表于: 2002/09/03 05:02pm
|
[quote][b]下面引用由[u]nico[/u]在 [i]2001/12/23 01:40pm[/i] 发表的内容:[/b] include<stdio.h> char * getstr() { char tmpstr; ... [/quote]char str[255] 申明的变量在 stack 中, 函数返回后就不确定了。编译成功只是巧合。malloc 出来的空间是在 heap 中,在进程的生存期都有效。所以 sinbad 和 badeager 的方法是最安全的。
|
| |
|
tianzhushan |
发表于: 2002/09/08 10:42am
|
这个函数的为什么没有输出为乱码? #include <stdlib.h> #include <stdio.h> #include <string.h> char *getmemory(void) { char p[]="hello world"; return p; } void test(void) { char str[100]; int i=0,len; strcpy(str,getmemory()); printf("the str is:%s\n",str); }main() { test(); }
|
| |
|
sonice |
发表于: 2002/09/08 10:39pm
|
楼上的程序没有出错是巧合。解释如下: char p[] = "hello world"; --> p 的空间在栈中,函数返回后栈空间就是自由空间了,可能被其他函数使用。你的函数没有出错是因为没有其他函数使用 p 所在的空间,但不能保证每次都这样。简单的程序不能说明问题,也证明不了什么。malloc 或者 new 出来的空间是在堆中,堆中声明的空间如果你不释放(free or delete),在整个进程的生存期都不会被改变。btw: malloc 系列函数中有一个可以强迫在栈中声明空间,这种空间不用去释放。 |
| |
|
fred08 |
发表于: 2002/10/11 10:20am
|
| 我看了各位的解决方案,很多都是可行的,但我认为还是flw的最好最全面,因为这样比较安全,不会留下bug。 |
| |
|
dongdongwx |
发表于: 2002/10/11 11:36am
|
能不用free的时候,最好不用她,不安全 给函数加一个字符串指针变量,好一点 |
| |
|
aegis |
发表于: 2002/10/13 02:55am
|
| 看来笨蛋不少 free 当然可释放 malloc 获得的内存了,不论是在哪个函数中申请的 你编译过去,“调试通过”,只不过是凑巧罢了,程序太简单了 读书去吧
|
| |
|
redgoat |
发表于: 2002/10/14 02:53pm
|
[这个贴子最后由redgoat在 2002/10/14 02:54pm 编辑]
sonice,你没搞错吧??!! 应该是静态内存才对,而并不是在栈中 |
| |
|
flw |
发表于: 2002/10/24 06:26pm
|
[quote][b]下面引用由[u]aegis[/u]在 [i]2002/10/13 02:55am[/i] 发表的内容:[/b] 看来笨蛋不少 free 当然可释放 malloc 获得的内存了,不论是在哪个函数中申请的 你编译过去,“调试通过”,只不过是凑巧罢了,程序太简单了 读书去吧 [/quote] 我同意这位仁兄的观点,我认为许多同学们还是应该把多读些语法方面的书,把语法重视起来,不要象我在别的地方听到的一样,竟然说潭老师的《C程序设计》罗罗嗦嗦,“没有实用价值”!
|
| |
|
紫竹 |
发表于: 2002/10/27 02:32am
|
| 原因是某一函数中的非指针变量是存放于栈中的,在退出时全部释放,因此这些局部变量也就没其存在的基础。但返回的指针变量可以是局部指针变量。 |
| |
|
lljsun |
发表于: 2002/10/29 10:40am
|
没有一点问题啊,我在sco unix上顺利编译运行,源代码一点没变。我觉得跟内存分配无关 char * getstr(){ char tmpstr[255]; strcpy(tmpstr,"------"); return tmpstr; } main(int argc,char argv[]) { char t[200]; strcpy(t,getstr()); printf("getstr() :%s\n",t); } |
| |
|
stonepine |
发表于: 2002/10/29 10:57am
|
taodale说得对,malloc()出来的内存区如果程序没有通过free()释放,会一直存在,即使程序退出,也会继续存在,只是此时变成不可访问的无用内存了。而临时变量以及数组则有它严格的作用域,由编译器分配和释放内存,redwoods在上面的帖子中没有注意变量的作用域问题,应该写成如下代码: void test(void) { char * teststr; teststr= malloc(200); //do something,but not free teststr return teststr; } int main(void) { char *teststr; teststr = test(); if ( teststr ) free(teststr) ; exit(0); }
|
| |
|
xiangzg |
发表于: 2002/10/29 11:41am
|
| 多了解一下c和c++编译系统,如果想做个好的程序员! |
| |
|
zglcl008 |
发表于: 2002/10/29 08:02pm
|
| free()能在函数外释放内存 |
| |
|
cloudqin |
发表于: 2003/01/07 04:30pm
|
这个问题太弱智了!不知道是不是刚写程序的菜菜! 在函数内定义的char数组是属于堆栈内的,函数退出就被释放了,简单点可以这样: void getstr(char* tmpstr){ strcpy(tmpstr,"------"); }mani() { char tmpstr[255] = {0}; getstr(tmpstr); /////do u anything//// printf("%s", tmpstr); }
|
| |
|
晴天羽 |
发表于: 2003/01/08 11:23am
|
最好的用法还是用变量传递。 void getstr(char *p, int inlen) { p = (char *)malloc(inlen); strcpy(p,"------"); return p; }
|
| |
|
taige |
发表于: 2003/01/08 03:45pm
|
楼主的做法肯定是不对的, 即使在小的程序中, 表面上运行没有问题(楼上一些仁兄所列), 但是大程序中就不敢肯定没有问题, 实际上这应该算程序的一个大BUG。当然在函数里面进行malloc()内存动态分配不会有问题, 但是要记得调用free()。 free的参数只是一个内存指针, 只要它指向的内存空间由malloc分配且未被free, 不用管在哪个函数里面由malloc分配的。 用static定义函数内的字符串变量也可以, 这样的话函数返回的时候, 该变量就不会释放,也就不会有问题。 当然,可以把一个字符串作为参数传入函数, 但是“晴天羽”的做法 :emn20: 推荐在调用函数前定义好足够长的字符串变量。 个人觉得还是用static定义变量最简单 :em11: |
| |
|
|