2012-09-13 42 views
0

可能重複:
Can a local variable's memory be accessed outside its scope?返回的局部變量的行爲的地址

輸入:

#include <stdlib.h> 
#include <stdio.h> 
int func2(void); 
int* func1(void); 

int func2(void) 
{ 
    int* b; 
    b = func1(); 
    printf("%d", *b); 
    printf("%d", *b); 
    printf("%d", *b); 
} 

int* func1() 
{ 
    int a = 13; 
    return &a; 
} 

int main() 
{ 
    func2(); 
} 

輸出:

13 -1077824828 -1077824828 

有人可以解釋堆棧和操作系統中發生了什麼?爲什麼在得到指針的值後結果從13變爲垃圾?

+4

重複數字無限加1。這是未定義的行爲。 –

+0

此外,'func2'不返回任何東西,儘管它的返回類型爲int。 –

+0

要真正回答這個問題:在你的特定情況下,第一次調用'printf()'覆蓋從調用到'func1()'時堆棧剩餘的'13'。 – Mysticial

回答

1

當然。 調試和發佈(清理)結果不同。 如果您查看程序集,則局部變量是EBP-(某些偏移量)。 這意味着更高層疊,如「更遠」。

這是您返回的地址。

通常情況下,如果函數返回就不會觸動。在某些編譯器的調試版本中,它會被有意識地刪除,以幫助您更快地捕獲懸掛指針錯誤。現在,printf調用重用堆棧中的相同地址來傳遞參數和自己的局部變量(它有一些)。它們將被寫入到由func1 return清空的地址,從而覆蓋您獲得的地址指向的任何地址。

+0

爲什麼printf會將參數傳遞給堆棧?他們不是直接發送到標準輸出緩衝區嗎? – Nizarazo

+0

不,它們很重要:生成調用者代碼的編譯器不知道「printf」是什麼意思,特別是這個函數要做什麼 - 比如使用stdout。 –

1

調用printf創建一個新的堆棧框架,覆蓋之前由a佔用的位置。

+1

也許,或者不是。你不能真正推理一下當你調用未定義的行爲時會發生什麼。 –

+0

當然可以。迪馬是對的。它是完美定義的,但依賴於平臺。 –

相關問題