-
1 # TonyDeng
-
2 # 重慶葉宏
C/C++結構體返回時,明顯克隆了一份,就象返回一個整數似的理解。這克隆出的一份結構體,應該在呼叫者的棧中。
-
3 # 蝸牛怪
首先說明一個問題,雖然返回值在函式內部聲名並且使用,但函式返回值在返回前從原變數進行資料的轉移,這是因為函式呼叫完畢,其棧要進行回收,這時棧裡面的記憶體變值雖然還可以訪問,但其已經標記為回收(因為函式返回後或呼叫完畢後esp棧進行了平衡,關於函式呼叫方式,我錄了一個影片,你可以點選檢視)。
下面我們來說一下函式的返回值,在返回時這個值的轉移問題:
當函式的返回值型別為基本資料型別時(雙精度浮點型以及非標準的__int64型別除外)作為返回值時,透過暫存器eax來儲存返回的資料,而對構體或者類物件等複雜資料屬於自定義型別,暫存器eax無法儲存物件中的所有資料,所以在函式返回時,暫存器eax無法滿足需求。
對於暫存器eax無法儲存返回的資料型別時,在函式呼叫前,編譯器會預先將要返回的資料記憶體空間使用的棧(注意,這裡是呼叫者的棧空間預留)保留出來,這樣當函式在退出時,將返回值的資料複製到預先分配的記憶體棧空間,以這個臨時空間的首地址作為首地址作為返回值。由於這個臨時空間是呼叫者函式內部的棧空間,所以說是可用的。
下面我將一段程式碼為例:
-
4 # Hypervisor
因為函式的返回值並不會放在記憶體中,更不會當到棧中,而是放到了CPU內部的通用暫存器裡面,具體是放在哪個暫存器,就要看那個CPU的架構了,X86的話,是放在了eax暫存器和edx暫存器中。
-
5 # 懶蟲o重複了o
這樣做90%是錯誤的。
1.指標是一個記憶體地址,當函式執行完畢就會釋放區域性變數,這個指標指向的地址就會出錯,函式外面再訪問這個地址就會出錯。
2.結構。當函式返回會將區域性變數賦值給你函式外的變數,然後就釋放這個區域性變數。例如std::string。
std::string test(){
std::string a=“abc”; //區域性變數a
return a;}
void main(){
std::string b = test(); //變數b,函式返回時會將區域性變數a賦值給b
//
printf(b.c_str()); //這裡訪問不會出錯
}
但這種方法和其他語言互調時會有相容問題。
剩下的%10
例如gethostbyname函式內部是將值儲存在一個全域性變數裡。所以返回指標不會出現問題。呼叫完gethostbuname再訪問他的返回值不會記憶體出錯。但這種方法會出現執行緒同步問題。也不推薦使用這種方法。
想要返回指標必須是函式內部用malloc或new申請記憶體,在函式體內不釋放,在函式外呼叫釋放即可。弊端是容易造成記憶體溢位。想要解決記憶體溢位就使用智慧指標。
回覆列表
函式返回的是值,這個值可以是指標或引用,但不管是指標還是引用,所指向的物件都不能是存在於棧中的,可以存在於堆中,即可以返回指向堆物件的指標,不可以返回指向棧物件的指標,引用亦然。
資料在棧中,是會被後續程式碼使用,但並不必然被用到所指向的位置,它有機會是仍然可尋並存在的,故此不能因為某些“試驗”可以找到這些資料就認為必然可以如此。
棧空間使用壓入式後進先出機制,資料會自動銷燬(最先入的未必會被彈出銷燬故有僥倖被返回指標尋訪的機會),堆空間是不會自動銷燬資料的,這就是用mallic()之類動態分配函式得到的物件必須主動用free()銷燬的原因,忘了這個動作,就是所謂的記憶體洩漏(資料霸佔堆空間或因指標丟失而無法尋訪),指標的風險實際上也在這裡。