[补遗]为什么那么烫?

考虑到明天会有大降温,学校澡堂把水加热到了一个足以导致水分子裂变的温度,让我着实感受了一把栈溢出。

几乎每个程序员都会看过这么一张图

original_VSpo_093700003460118d

说起来电脑又没去澡堂为什么那么烫呢?

我们知道(也许只是我知道),“使用VC(VC2005/VC2008)编译程序时,如果你启动了“/RTC1”(VC6使用/GZ)去编译调试模式的程序,那么程序运行时VC的运行库就会使用特定的值填充申请和释放的内存,在调试内存错误时非常有用。

0xCC:填充未初始化的栈变量。 在GBK编码中“烫”的编码为CCCC(GBK编码是对常用中文的编码)

0xCD:填充从堆中申请的内存。 在GBK编码中“屯”的编码为CDCD

0xDD:已经释放的内存。

0xFD:填充应用程序申请内存的前后的内存(前面4个字节,后面4个字节)。”

简而言之,因为VC默认使用0xCC来填充开辟的栈,用0xCD填充刚开辟的堆。两个CC正好凑成了GBK编码中的烫,两个CD凑成了屯。所以我们会在栈溢出时会看到一堆“烫”,而在堆溢出是看到一堆“屯”。

另一个问题也简单探究一下,为什么默认要用CC来填充栈空间呢?

因为0xCC对应是int 3h的机器码

“__asm int 3h 通常用来debug, int 3h 提交一个debug exception

被cpu捕捉,通过IDT,映射到OS的exception handler.

实际上,VC 的debugger会在debuggee的地址空间的断点处写入一条 __asm int 3h

这样,debuggee执行到断点时,会出发一个异常,进入kernel. OS再

对这个异常进行派发,在NT下通过LPC提交给debugger.”

再次简而言之,3h就相当于系统的中断向量表中对应了debug中断的编码,系统捕捉到后直接交给debug处理。

涉及的知识太偏硬件,有点力不从心,关于INT 3中断的参见这里

为什么填充堆要使用0xCD?留待高手指导。

参考资料:

代码疯子的博客

IT专业技术交流平台

PCHome

发表评论