vc 编译g 出现问题出现烫烫烫烫烫烫是为什么

人人网 - 抱歉
哦,抱歉,好像看不到了
现在你可以:
看看其它好友写了什么
北京千橡网景科技发展有限公司:
文网文[号··京公网安备号·甲测资字
文化部监督电子邮箱:wlwh@··
文明办网文明上网举报电话: 举报邮箱:&&&&&&&&&&&&烫烫烫”——调试基础断点篇 - 夸克# - 博客园
很多人都应该见过&烫烫烫&这个神一般存在的字符串,一旦&烫烫烫&出现的时候,就说明你玩坏了&&指针越界,访问到了非法内存。
那么为啥是&烫烫烫&,跟断点有啥关系?
我们在用VC进行调试时,常常会观察到一块刚分配的内存或字符串被填满了&CC&,而0xCCCC正好是&烫&这个汉字的GB2312编码。另外很巧的是 0xCC又正好是INT3指令的机器码。这显然不是什么巧合,而是我们的编译器故意这么做的。至于原因,先看INT3这条指令是干嘛的?
x86架构下提供了一条专门用来支持调试的指令,即INT 3。这条指令的目的是使CPU中断到调试器。
看下面一个简单的例子:
在调试状态下执行INT 3指令,程序就会断下来并提示这是一个Break instruction exception(上图右半部分)。并且从上图可以看到INT 3的机器码是0xCC。
所以,编译器在调试状态下会把未初始化的缓冲区填充为0xCC(0xCD),目的就是为了因缓冲区溢出等原因程序指针指向了这块区域,遇到INT 3指令而中断到调试器。
PS: 在实际的代码中,INT3也是能派上用场的。曾经在调试一个程序的时候,需要在一个宏里面下断点,而通过VS是没法直接在宏里面下断点的。所以当时做了一件事情,就是在宏里面需要断下来的地方加入了INT 3,这样程序一旦跑起来到这个地方就会自动断下来。
软件断点是我们最常用的断点,用来在程序代码中设置断点。当代码执行到断点所在行时程序便会断下来,这个时候可以通过调试器观察,修改此时寄存器上下文,内存数据等。
软件断点实现的原因正是通过INT 3指令来实现的
我们在VS,Windbg等调试器中设置一个断点的时候,究竟发生了什么?
l& 调试器首先会在内存映射中找到对应的断点位置;
l& 将断点位置的第一个字节替换成0xCC,即INT 3,然后将被替换的这个字节保存起来;
l& 一旦程序执行到INT 3指令,就会产生一个断点中断到调试器,这就是断点命中;
l& 当用户恢复程序运行时,调试器实际做的事情就是恢复INT 3指令替换的那个字节,让程序按照原指令执行。
我们做个实验来验证一下:
对于如下代码:进程为breakpoint.exe
我们用VS在第10行printf语句设置一个断点,然后将程序在VS下运行起来,主要不要让代码跑到断点处。
这个时候我们用Windbg也挂住breakpoint.exe进程,查看第9行代码的反汇编:
可以看到第一个指令就是INT 3,现在我们用VS中同样查看一下第9行汇编:
为啥同样的进程状态下,两个调试器看到的指令不一样,因为VS是设置断点的时候存储了被INT 3指令替换的那个字节的内容,所以在UI上展示的时候VS可以还原原始代码的情况,而实际上Windbg展示的才是进程当前真实的指令。原始代码本身是&movesi, esp&指令,机器码是0x8bf4,因为第一个字节0x8b被替换成了0xCC,所以导致windbg下面看到的下一个字节0xf4被解析成了&hlt&指令。
使用INT 3指令产生的断点是依靠插入指令和软件中断机制工作的吗,因此把这类断点称为软件断点。但是软件断点也有局限性:
l& 可以让CPU执行到代码的某个地址停下来,但不适用于数据段和I/O空间;
l& 对于在ROM中执行程序,无法动态的添加软件断点,因为目标内存是只读的。
l& 依赖于中断机制的正常运行,如果中断向量表或者中断描述表没有准备好或者被破坏,软件断点是无法正常工作的。
硬件断点之所以&硬&,是因为硬件断点依赖硬件。英特尔从386开始,增加了调试寄存器和硬件断点的特性。
IA-32架构定义了8个调试寄存器,其中4个用来存储断点地址,2个寄存器保留,1个调试控制寄存器,1个调试状态寄存器。也就是说,最多可以设置4个硬件断点。
硬件断点有什么作用:
l& 读写内存中的数据中断;
l& 执行内存中的代码中断(作用类似于软件断点);
l& 读写I/O端口时中断;
我们日常工作中最常用到的硬件断点的场景就是&读写内存中的数据中断&,即监控某个内存地址读写,也叫内存断点。特别是在多线程环境下监控某些全局变量的状态,有时候能起到奇效。
设置一个硬件断点,本质上就是将要监控的地址写入到一个调试寄存器,以及把相关的控制选项写入到控制寄存器。一旦满足调试寄存器中设置的状态,断点就会被触发。看个例子:
如上代码,变量flag初始化后并没有被使用,但是打印出来的值却不是0x123。
当然,以上这个例子很容易发现对数组a的访问越界了,而实际项目出问题的代码往往是很难直接看出问题原因的。
我们来调试一下以上代码,看看究竟是什么时候flag的值被修改的。
1.&&&&&& 首先用Windbg启动被调试程序breakpoint.exe;
2.&&&&&& 设置断点到main函数:bpbreakpoint!wmain;
3.&&&&&& 运行程序到断点处:main函数的入口处;
4.&&&&&& 通过dv /V命令查看当前栈帧的局部变量信息;
5.&&&&&& 知道了flag变量的地址是002cf9f0,设置一个硬件断点监控地址为002cf9f0的写行为。
下面是8个调试寄存器的值:
dr0被设置成了我们要监控的地址,dr6,dr7分别是调试状态寄存器,调式控制寄存器。
上图展示了两个断点,第一个是我们之前设置的软件断点,第二个就是硬件断点:参数w表示只监控该地址的写行为,4表示监控长度为4个字节。
6.&&&&&& 继续运行程序,会遇到第一次中断:
断下来的这句指令是将栈帧部分填充为0xCCCCCCCC,&烫烫烫&又出现了。另外这段初始化指令只在调试版本中才会有。
7.&&&&&& 继续运行程序,第二次断下来:
这次是因为对变量flag赋值为123而断下来,意料之中。
8.&&&&&& 第三次断住:
以上指令是将ecx的值5赋值给正好是flag所在的内存地址:ebp + eax * 4 & 20h == ebp& 0x0C。
是第18行代码干的,也就是说因为数组访问越界从而影响到了flag的值!
硬件断点功能强大,但是最大的缺点受限于硬件&&数量限制,最多4个。C 语言代码出错为什么显示「烫烫烫」,而不是其它字?_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
C 语言代码出错为什么显示「烫烫烫」,而不是其它字?
上传于||暂无简介
你可能喜欢}

我要回帖

更多关于 java编译出现乱码 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信