閱讀《c專家程式設計》中,描述乙個sun的pascal編譯器出現的bug——編譯器日期被破壞。這個bug點出c/c++中的函式返回區域性變數可能存在的問題:
1、如果函式返回的是區域性變數的值,程式不會出現問題;
2、如果函式返回的是區域性變數的指標(位址),可能會出現問題。
書中給出的**如下:
char * localized_time(char *filename)
然而,在實際的編譯(32bit-win7+vs2008環境)中,會出現問題,可能是windows和unix之間的差異,具體留後面討論。
書中講到:在c語言中,自動變數在堆疊中分配記憶體。當包含自動變數的函式或**塊退出時,它們所占用的記憶體便被**,它們的內容肯定會被下乙個所呼叫的函式覆蓋。這一切取決於堆疊中先前的自動變數位於何處,活動函式宣告了什麼變數,寫入了什麼內容等。原先自動變數位址的內容可能被立即覆蓋,也可能稍後才被覆蓋。
解決方案如下幾種:
1、返回乙個指向字串常量的指標。(此方案太過於侷限)
2、使用全域性宣告的陣列。
char *func()
缺點:<1>、任何人都有可能在任何時刻修改這個全域性陣列;
<2>、該函式的下一次呼叫也會覆蓋該陣列的內容;
<3>、浪費記憶體空間(尤其是陣列比較大的情況)。
3、使用靜態陣列。
char *func()
優點:可以防止任何人修改該陣列,只有擁有指向該陣列的指標的函式才能修改該靜態陣列(通過引數傳遞)。
<2>、浪費記憶體空間(尤其是陣列比較大的情況)。
4、顯示分配一些記憶體,儲存返回的值。
char *func()
優點:<1>、可以防止任何人修改該資料,且該函式在下次被呼叫不會覆蓋以前的返回值;
<2>、適用於多執行緒的**。
缺點:需要承擔記憶體管理的工作,容易產生記憶體洩漏。
5、出參的方式返回陣列,由呼叫者管理記憶體分配與**(推薦)
void func(char *result,int size)
buffer =malloc(size);
func(buffer,size);
...free(buffer);
最好在同一**塊同時進行「malloc」和「free」操作,遵循誰分配,誰釋放的原則。
好了,分享了作者的闡述,下面是我的通過編譯的測試**。
#include "stdafx.h"
#include #include #include char * localized_time(char *filename)
int main(void)
遇到兩個問題:
1、書中給出的**段:strftime(buffer,sizeof(buffer),"%a %b %e %t %y",tm_ptr);執行是產生崩潰。
原因是strftmie.c第832行丟擲異常,_asserte( ( "invalid format directive" , 0 ) );
結合strftmie.c中的源**及msdn。是因為strftime()函式沒有「%e和%t」,這裡可能是windows和unix的差異?沒有深究。
2、執行上述修改過的**後,發現:
<1>、呼叫函式可以列印出正確的返回值;
<2>、如果把buffer[120]改為buffer[90],呼叫函式
可以列印出正確返回值的一部分+亂碼;
<3>、如果把buffer[120]改為buffer[90],呼叫函式列印的結果為空;
<4>、注釋掉 「printf("strftime:%s\n",buffer);」,呼叫函式
列印的結果為亂碼。
這也印證了如果函式返回的是區域性變數的指標(位址),可能會出現問題。
zhaipillary
2015/05/21 於上海
函式返回區域性變數的問題
1.返回區域性變數的值 可以有兩種情況 返回區域性自動變數和區域性靜態變數,比如,int func 區域性變數temp儲存在棧中,函式返回時會自動複製乙份temp的copy給呼叫者,沒有問題。int func 區域性變數a儲存在靜態 全域性 儲存區中,從初始化後一直有效直到程式結束,僅分配一次記憶體...
函式返回區域性變數的問題
1.函式可以返回區域性變數 當函式的區域性變數作為函式的返回值時,其實是不知道是誰 是程式?會自動生成乙個變數的副本即拷貝作為函式的返回值,而原有的區域性變數將被銷毀。注意函式不可以返回區域性變數的位址或者某個指標,以為當函式執行完了 這裡改咋說 系統會 這塊位址,因此這個位址裡面 的東西也就沒有意...
函式返回區域性變數
一般的來說,函式是可以返回區域性變數的。區域性變數的作用域只在函式內部,在函式返回後,區域性變數的記憶體已經釋放了。因此,如果函式返回的是區域性變數的值,不涉及位址,程式不會出錯。但是如果返回的是區域性變數的位址 指標 的話,程式執行後會出錯。因為函式只是把指標複製後返回了,但是指標指向的內容已經被...