在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; }