|  |  |  |  |  |  | 
					            
						            
							            
								            |  | 
	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: 子函数里的局部变量,使用的是栈内存,子函数返回后,该栈内存被谁清掉了? |  |  
 |  |  |  |