http://stor.chinaunix.net/bbs/archiver/tid-897190.html
题目如下
栈内存何时释放?
char * func1()
{
char a[10];
char *p;
strcpy(a,"abc");
p = a;
return p;
}
main()
{
char *p;
strcpy(p,func1());
printf("%s/n",p);
}
打印结果:abc
栈内存是在cp之后释放的吗?
char * func1()
{
char a[10];
char *p;
strcpy(a,"abc");
p = a;
return p;
}
main()
{
char *p;
strcpy(p,func1());
printf("%s/n",p);
}
打印结果:abc
栈内存是在cp之后释放的吗?
首先程序就有个错误
在main() 中,char* p 只有声明,没有定义
后面却strcpy ,所以编译不通过。
改成char* p=new char[8];
结果p 是指向"abc"的,很多说是偶然,其实偶然中存在这必然,我们先看怎么改变堆栈,是其不指向"abc"呢
void func2()
{
char x[10];
for(int i=0;i<10;i++)
{
x[i]='o';
}
}
{
char x[10];
for(int i=0;i<10;i++)
{
x[i]='o';
}
}
main这样写
char *p=new char[10];
char* d=func1();
func2();
strcpy(p,d);
func2();
strcpy(p,d);
printf("%s/n",p);
结果改变了,func2()改变了堆栈内容
为什么strcpy没有改变堆栈呢,估计要从汇编上看了,、
strcpy 不是stdcall,而是_cdecl,从后面的add esp,8看出
_cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,
我们用od跟下,下面是strcpy的前面的汇编
102AEC50 > 57 push edi
102AEC51 8B7C24 08 mov edi, dword ptr [esp+8]
102AEC55 EB 6E jmp short 102AECC5
102AEC57 8DA424 00000000 lea esp, dword ptr [esp]
102AEC5E 8BFF mov edi, edi
102AEC60 > 8B4C24 04 mov ecx, dword ptr [esp+4]
102AEC64 57 push edi
102AEC65 F7C1 03000000 test ecx, 3
102AEC6B 74 13 je short 102AEC80
102AEC6D 8A01 mov al, byte ptr [ecx]
102AEC6F 83C1 01 add ecx, 1
102AEC72 84C0 test al, al
102AEC74 74 3D je short 102AECB3
102AEC51 8B7C24 08 mov edi, dword ptr [esp+8]
102AEC55 EB 6E jmp short 102AECC5
102AEC57 8DA424 00000000 lea esp, dword ptr [esp]
102AEC5E 8BFF mov edi, edi
102AEC60 > 8B4C24 04 mov ecx, dword ptr [esp+4]
102AEC64 57 push edi
102AEC65 F7C1 03000000 test ecx, 3
102AEC6B 74 13 je short 102AEC80
102AEC6D 8A01 mov al, byte ptr [ecx]
102AEC6F 83C1 01 add ecx, 1
102AEC72 84C0 test al, al
102AEC74 74 3D je short 102AECB3
呵呵,inline吗 ? 只有一句push edi 破坏堆栈,根本影响不到前面call 的局部变量
所以总结一下:
返回堆栈数据,后边的call 不必须是strcpy ,memcpy不破坏堆栈的call,否则,后果不难想象!
题目中的语句也可以这样写
char* d=func1();
strcpy(p,d);
效果是一样的