|
|
|
|
|
|
|
C/C++本地代码调试
帖子发起人: nanjingesc 发起时间: 2010-05-25 12:34 下午 回复: 5
|
帖子排序:
|
|
|
|
2010-05-25, 12:34 下午
|
nanjingesc
注册: 2010-02-24
发 贴: 8
|
子函数里的局部变量,使用的是栈内存,子函数返回后,该栈内存被谁清掉了?
|
|
|
|
char * GetString(void)
{
char p[]="hello,world";
return p;
}
void main(void)
{
char *str=NULL;
str=GetString(); }
现在问题就是:子函数的p数组在栈内存里,通过寄存器AX把这个栈地址返回了。
c 语言子函数返回的时候会保持栈平衡,所用的手法就是mov sp,bp,
通过debug调试发现,在该语句执行前,堆栈里的数据"hello,world"还在,
执行该语句后,堆栈该处的数据就变化了,变得不再是"hello,world",
所以想问下:堆栈平衡,仅仅是移动了sp指针,为什么会把原来栈里的数据清掉了呢?
又或者说是谁去做这样的事情呢?编译器,操作系统,还是CPU本身的机制呢?
我在WINDOWS的CMD窗口,和软盘启动的DOS都试过,结果一样。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2010-05-25, 18:38 下午
|
luobing
注册: 2009-10-06
发 贴: 19
|
Re: 子函数里的局部变量,使用的是栈内存,子函数返回后,该栈内存被谁清掉了?
|
|
|
|
试验了,确实如此。与调试器有关。试验这样的代码:
char * GetString(void)
{
char p[]="hello,world";
return p;
}
char static_ptr[20];
void main(void)
{
char *str=NULL;
int i;
for(i=0;i<20;i++)static_ptr[ i ]=0;
str=GetString();
for(i=0;i<20;i++)static_ptr[ i ]=str[ i ];
printf("%s\n",str);
printf("%s\n",static_ptr); }
即在执行完GetString后直接将str中的值取出放入内存中,而不是作为局部指针存在。结果str打印出不确定字符串,static_ptr打印了hello,world.我们知道,局部指针指向的内存值在函数结束后是不确定的。
在非debug中,当函数执行到mov sp,bp的时候,实际上不会发生nanjingesc所叙述的情况(以上的例子证明了)。之所以在debug的环境中发生,是因为执行这条指令的时候,调试器本身也用到了堆栈,影响了这部分数据。同样的道理,为什么str打印出不确定的字符串,是因为printf影响了栈中的内容。这种现象不管用哪种调试器(当然是软件调试器,如TD,debug32等)应该都会发生。这个例子在林锐的书《高质量C/C++编程》中有叙述,但是他的描述不大准确,因为他的说法也是通过调试来发现数据变了,并没有说明这之间到底是怎么变化的。
我现在在想另外一个问题,如果使用JTAG来调试的话,会不会出现这样的问题。之前调试某款BIOS的时候遇到过,只要往sp中塞入一个值,如mov sp,200h(当然,我确定200h处是我自己规定的堆栈),200h处的数据立即就改变了,这个问题一直没有想明白,手上也没有类似的环境调试。张老师,看到的话能否帮助想想,谢谢^^
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2010-05-25, 20:10 下午
|
格蠹老雷
注册: 2005-12-19
发 贴: 1,303
|
Re: 子函数里的局部变量,使用的是栈内存,子函数返回后,该栈内存被谁清掉了?
|
|
|
|
呵呵,二位都想得很深入。
这里的一个关键问题是CPU在发生异常时会自动向栈里压入包括IP寄存器在内的当前位置信息(参见《软件调试》11.1.3 P278)。而在调试时,单步跟踪会触发异常,导致CPU向栈里压入信息。
对于保护模式,因为异常处理代码在内核模式,所以要切换到使用内核态的栈,因此用户态的栈一般不会受影响。对于实模式情况,不涉及栈的切换,CPU会直接使用当前的栈,因此就会看到CPU曾经使用的痕迹。
对于现在的例子,编译成32位程序和编译成16位,结果应该是有所差异的。
对于32位的情况,应该是不会变的,除非有用户代码会用到这个空间,对于本例,在GetString返回后,即使在有调试器的情况下,观察main函数的str变量,还是应该可以看到本来的内容的,直到再调用其它函数,再使用栈,这个内容便可能会被破坏了。
仔细看下,如果还有问题,可以把编译好的exe发到我信箱一份。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2010-12-22, 16:29 下午
|
Forward
注册: 2009-12-23
发 贴: 50
|
Re: 子函数里的局部变量,使用的是栈内存,子函数返回后,该栈内存被谁清掉了?
|
|
|
|
我对楼主说的现象觉得很奇怪,我这里测试,字符串是没有变化的,如果楼主确定变化的话,是否可以在调用前打内存断点,观察下。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2010-12-24, 14:43 下午
|
不及格的程序员-八神
注册: 2009-11-11
发 贴: 22
|
Re: 子函数里的局部变量,使用的是栈内存,子函数返回后,该栈内存被谁清掉了?
|
|
|
|
很明显,栈上的内存被回收或是被其它的数据占用了.
也就是说你的str中保存的很可能是野指针,指向谁已经不确定了.
不及格的程序员-八神
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2011-01-01, 12:32 下午
|
heye
注册: 2011-01-01
发 贴: 1
|
Re: 子函数里的局部变量,使用的是栈内存,子函数返回后,该栈内存被谁清掉了?
|
|
|
|
在计算机中,无论是删除内存还是删除硬盘文件,一般情况下,如果没有特殊要求,只是将该区域表记为可用就算释放了。由此,也就有所谓的数据恢复软件,即当你删除文件后,如果该区域没有被其他文件占用,那么就有可能被恢复。
因此你这个话题是个伪话题:根本没有什么机制来清,只有两个机制:一是改变sp指针,使得该区域重新可用;二是新的数据的进入改变了原来的数据。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
高端调试 » 软件调试 » C/C++本地代码调试 » Re: 子函数里的局部变量,使用的是栈内存,子函数返回后,该栈内存被谁清掉了?
|
|
|
|
|
|