函数返回char* 的解决方案
在C语言中,自动变量在堆栈中分配内存。当包含自动变量的函数或代码块退出时,它们所占用的内存便被回收,它们的内容肯定会被下一个所调用的函数覆盖。这一切取决于堆栈中先前的自动变量位于何处,活动函数声明了什么变量,写入了什么内容等。原先自动变量地址的内容可能被立即覆盖,也可能稍后才被覆盖。
解决方案:
1. 返回一个指向字符串常量的指针。例如:
char* func() { return "Only works for simple strings"; }
这是最简单的解决方案,但如果你需要计算字符串的内容,它就无能为力了,在本例中就是如此。如果字符串常量存储于只读内存区,但以后需要改写它时,你就会有麻烦了。
2. 使用全局声明的数组。
char* fun() { ................. global_array[i] = ....; return global_array; }
这适用于自己创建字符串的情况,也很简单易用。它的缺点在于任何人都有可能在任何地方任何时候修改这个全局数组。
3. 静态数组。例如:
char* func() { static char buffer[25]; ... return buffer; }
这就可以防止任何人任何时候修改这个数组。只有拥有指向该数组的指针的函数(通过参数传递给它)才能修改这个静态数组。但是,该函数的下一次调用将覆盖这个数组的内容,所以调用者必须在此之前使用或者备份数组的内容。和全局数据一样,大型缓冲区如果闲置不用是非常浪费内存空间的。
4. 显式分配一些内存,保存返回的值。例如:
char* func() { char *s = malloc(120); ... return s; }
这个方法具有静态数组的优点,而且在每次调用时都创建一个新的缓冲区,所以该函数以后的调用不会覆盖以前的返回值。它适用于多线程的代码。它的缺点在于程序猿必须承担内存管理的责任。根据程序的复杂程度,这项任务可能很容易,也可能很复杂。如果内存尚在使用就释放或者出现“内存泄露”(不再使用的内存未回收),就会产生令人难以置信的Bug。人们非常容易释放已分配的内存。
5. 也许最好的解决方案就是要求调用者分配内存来保存函数的返回值。为了提高安全性,调用者应该同时指定缓冲区的大小。
void func(char *result, int size) { ... strncpy(result, "That' d be in the data segment, Bob", size); } buffer = malloc (size); func(buffer); ... free(buffer);
如果程序员在同一块代码中同时进行“malloc” 和“free”操作,内存管理最为轻松。
6. const char* 返回
//错误 char* Func(void) { char str[] = "hello world"; return str; } //正确 const char* Func(void) { const char* p = "hello world";//字符串常量存放在程序的静态数据区 return p; }