char* GetString(void)
{
char p[] = "hello world"; //用字符串常量来初始化数组的内存空间
return p; //编译器将提出警告
}
int main()
{
char *p;
p = GetString();
}
代码交简单,函数错误原因:因为把申请的空间赋给了局部变量。但是想以汇编角度来审视代码,但是不太懂
main()
{
push ebp
mov ebp,esp //得到main栈的栈顶地址
sub esp,44h //为main栈开辟76个字节的区域用于局部变量使用
push ebx
push esi
push edi //需要保护的寄存器值压栈
lea edi,[ebp-4Ch]
mov ecx,13h
mov eax,0CCCCCCCCh
rep stos dword ptr [edi] //局部变量初始化,debug模式下是此值,release模式局部变量为不定值
char *p;
p=GetString();
call @ILT+20(GetString) (00401019)
mov dword ptr [ebp-4],eax
}
pop edi
pop esi
pop ebx
add esp,44h
cmp ebp,esp
call _chkesp(00408230)
mov esp,ebp
pop ebp
ret
问题1:跟进去,第18行已经出mian的作用域了,为何p的值还是对的“hello world”;
问题2:这代码如何看出函数里临时变量的栈已经弹出(以汇编角度分析此代码的问题所在)。
------解决思路----------------------
1.局部变量的弹出,只是把ESP修改回来啊。如果你取那个内存地址的值,他的内容还在那里啊。
2.add esp,44h
mov esp,ebp
这里就是恢复堆栈平衡了啊。不过刚才你写入的Hello world还在内存里面。
为什么会警告我现在想不出来。
我还是菜鸟,如有不对,请多指教.
------解决思路----------------------
你那个字符串在内容中的首地址是[ebp-0ch],在pop edi的前面他已经把地址给eax,eax中就是字符串的首地址,这指令执行完会变?想不通。
栈不是被清空了。只是把栈的指针给指向调用函数前的地址了,(不知道这样讲你理不理解),
sub esp,44h //为main栈开辟76个字节的区域用于局部变量使用
这个esp的值,就是栈顶的地址,你自己都写了。开辟了76个字节的栈空间给P了
add esp,44h,函数退出前,最后这句又把栈顶的地址给改回来了。它没有把开辟出来的76个字节给赋值成0,所以那些内存里面还是有你的字符串在的。