題目:分析下面代碼的運行結果。
#include <stdio.h>char *GetMemory(){char a[] = "hello,world";/*char *a = "hello,world";//這樣聲明的話有效 */return a;}int main(int argc, char *argv[]){printf( "%s\n", GetMemory() );getchar();return 0;}
運行結果是:輸出亂碼或者程式崩潰。原因是a指向的臨時記憶體位址在函數調用完了之後,對應的空間已經釋放,再去訪問的話,是非法的。
分析:在VS2012下面, 程式執行後出現亂碼,因為函數返回時,函數內的棧空間已被清除。
注意:對於字串"hello,world"而言,他所在的空間不是棧,而是堆,所以一開始我覺得本程式執行的結果是可以正常輸出的,但是,實際結果並非如此。經反組譯碼發現,函數GetMemory的操作不是使得a指向堆裡面的字串,而是把堆裡面的字串拷貝一份到棧裡面,所以函數調用完之後,返回的地址是棧內的地址,而函數完了之後棧會自動清除,所以會出現亂碼。但是如果a的聲明是指標(int *a),而不是數組,那麼可以正常輸出,因為函數內部的a指向的是堆裡面的字串,所以返回的地址有效。
反組譯碼代碼如下:
;;兩個不同的版本;;數組;;這個是har a[] = "hello,world";的反組譯碼代碼char a[] = "hello,world";;下面的這一段是實現堆內字串拷貝到棧內的00AC1AE8 mov eax,dword ptr ds:[00AC5858h] 00AC1AED mov dword ptr [a],eax 00AC1AF0 mov ecx,dword ptr ds:[0AC585Ch] 00AC1AF6 mov dword ptr [ebp-10h],ecx 00AC1AF9 mov edx,dword ptr ds:[0AC5860h] 00AC1AFF mov dword ptr [ebp-0Ch],edx ;;指標;這個是char *a = "hello,world";的反組譯碼代碼char *a = "hello,world";01001ADE mov dword ptr [a],1005858h