题目:分析下面代码的运行结果。
#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