烫烫烫烫烫烫烫烫烫烫烫烫烫 屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯

烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫
是debug中未初始化的栈变量

屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯
是debug中未初始化的堆变量

 

 

0xcc  16进制数,相当于十进制的204

未初始化的变量
DEBUG模式下运行时,未初始化的变量会被系统赋初值为0xCC

未初始化的变量会被系统赋初值为0xCC,超过了ASCII码0-127这个范围,因此这个“字符串”被系统当成了宽字符组成的字符串,即两个字节数据组成一个字符,而0xCCCC表示的宽字符正好是乱码中的那个“烫”字。

 

烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫
是debug中未初始化的栈变量
屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯
是debug中未初始化的堆变量

 

 

 浅析"烫烫烫烫"是怎么来的

浅析"烫烫烫烫"是怎么来的

在用VC写代码时,经常会遇到在栈中申请空间的并且没有被初始化的字符数组就会显示"烫烫烫烫。。。",虽然是知道编译器对栈中没有初始化的数据会进行默认的初始化工作,但是一直不得要领,在拜读《程序员的自我修养》的时候有所收获,还挺有意思的,写出来和大家分享。

代码很简单,就是在栈中申请了一个大小为4个字节的字符数组。

 

  1. int  main( void )    
  2. {    
  3.     char  x[4];    
  4.     return  0;    
  5. }    

 

用断点查看X的值,可以发现,“烫烫”出现了:

x 0x0012ff60 "烫烫烫烫?" char [4]

查看反汇编:

 

  1.   1:  int  main( void )    
  2.      2: {    
  3. 004113A0 55               push        ebp      
  4. 004113A1 8B EC            mov         ebp,esp     
  5. 004113A3 81 EC CC 00 00 00 sub         esp,0CCh     
  6. 004113A9 53               push        ebx      
  7. 004113AA 56               push        esi      
  8. 004113AB 57               push        edi      
  9. 004113AC 8D BD 34 FF FF FF lea         edi,[ebp-0CCh]     
  10. 004113B2 B9 33 00 00 00   mov         ecx,33h     
  11. 004113B7 B8 CC CC CC CC   mov         eax,0CCCCCCCCh     
  12. 004113BC F3 AB            rep stos    dword ptr es:[edi]     
  13.      3:     char  x[4];    
  14.      4:     return  0;    
  15. 004113BE 33 C0            xor         eax,eax     
  16.      5: }   

 

简单解释一下关键句的含义:

004113AC 8D BD 34 FF FF FF lea         edi,[ebp-0CCh]

将获得的0CCh大小的栈空间首地址赋给edi

004113B2 B9 33 00 00 00   mov         ecx,33h

rep的循环次数为33h
004113B7 B8 CC CC CC CC   mov         eax,0CCCCCCCCh

eax = 0CCCCCCCCh 
004113BC F3 AB            rep stos    dword ptr es:[edi]

将栈空间的33H个双字节赋值为0CCCCCCCCh

而0xcccc用汉语表示刚好就是“烫”

oxcc正好是中断int 3的指令 起到保护作用

 

 

为什么DEBUG的时候,内存里都是“烫烫烫烫烫烫烫烫烫……”呢?

 

是内存太热了吗?哈哈,当然不是。。

以下转自CSDN

在   Debug   模式下会自动加上   /GZ   编译选项,它可以帮助捕获内存错误。   
    
  /GZ   选项会做以下这些事   
    
  (1)   初始化内存和变量。包括用   0xCC   初始化所有自动变量,0xCD   (   Cleared   Data   )   初始化堆中分配的内存(即动态分配的内存,例如   new   ),0xDD   (   Dead   Data   )   填充已被释放的堆内存(例如   delete   ),0xFD(   deFencde   Data   )   初始化受保护的内存(debug   版在动态分配内存的前后加入保护内存以防止越界访问),其中括号中的词是微软建议的助记词。这样做的好处是这些值都很大,作为指针是不可能的(而且   32   位系统中指针很少是奇数值,在有些系统中奇数的指针会产生运行时错误),作为数值也很少遇到,而且这些值也很容易辨认,因此这很有利于在   Debug   版中发现   Release   版才会遇到的错误。要特别注意的是,很多人认为编译器会用   0   来初始化变量,这是错误的(而且这样很不利于查找错误)。   
    
  (2)   通过函数指针调用函数时,会通过检查栈指针验证函数调用的匹配性。(防止原形不匹配)   
    
  (3)   函数返回前检查栈指针,确认未被修改。(防止越界访问和原形不匹配,与第二项合在一起可大致模拟帧指针省略FPO)   
    
  “烫”字的MBCS编码为“CCCC”,而用   /GZ   选项对自动变量会用“0xCC”初始化,连续的“0xCC”将被误读成“烫”字符。

 

 

例子:

char strBusID[5 ];
memset(strBusID,0,5 ); // 把5个字节全部清0,最关键的就是把strBusID[4]置为'/0'
char* filebuffer ="x10001192.168.100.224asdfghijklmnopqrstuvw";
memcpy(strBusID,(filebuffer +2),4);

char s[]这样的字符串实质上是数组,它是依靠'/0'来标记字符串结尾的。
如果0001之后没有'/0',他就会把后续内存里的内容取出来,直到遇到一个'/0'为止。
注意区别'/0'和'0'。'/0'对应ascii的0,'0'对应ascii码的48。
DEBUG模式下运行时,未初始化的变量会被系统赋初值为0xCC ,超过了ASCII码0-127这个范围,因此这个“字符串”被系统当成了宽字符组成的字符串,即两个字节数据组成一个字符,而0xCCCC表示的宽字符正好是乱码中的那个“烫”字。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值