程序代码:
char testc=0xf1;
char testbuf[3]={0};sprintf(testbuf, "%02X", testc);
上面代码咋看是没有问题的或者你简单运行这样一段小程序不会出错,但是在一个大的工程中会引发内存溢出。
比如出现:CString Run-Time Check Failure #2 - Stack around the variable 'tmp' was corrupted.这样的错误
为什么会引发内存溢出。我们来看看其对应的汇编指令就一目了然了。
char testc=0xf1;
0041F322 mov byte ptr [ebp-1Dh],0F1h
char testbuf[3]={0};
0041F326 mov byte ptr [ebp-2Ch],0
0041F32A xor eax,eax
0041F32C mov word ptr [ebp-2Bh],ax
sprintf(testbuf, "%02X", testc);
0041F330 movsx eax,byte ptr [ebp-1Dh]
0041F334 mov esi,esp
0041F336 push eax
0041F337 push offset string "%02X" (45314Ch)
0041F33C lea ecx,[ebp-2Ch]
0041F33F push ecx
0041F340 call dword ptr [__imp__sprintf (48AC90h)]
0041F346 add esp,0Ch
0041F349 cmp esi,esp
0041F34B call @ILT+3880(__RTC_CheckEsp) (41AF2Dh)
上面加粗的那一行说明了为什么会出现溢出。原因如下:
首先说明一下movsx指令的意思:带符号扩展传送指令。符号扩展的意思是,当计算机存储某一个有符号数时,符号位位于该数的第一位,所以,当扩展一个负数的时候需要将扩展的高位全赋为1. 对于正数而言,符号扩展和零扩展movsx是一样的,将扩展的高位全赋为0.
既然这样那么eax的值就变为0xfffffff1,此时再行格式化时testbuf势必装不下“fffffff1”8个字符,进而就出现了内存溢出。
修改方法有两种
第一种:
char testc=0xf1;
char testbuf[3]={0};sprintf(testbuf, "%02X", (unsigned char)testc);
第二种
char testc=0xf1;
char testbuf[100]={0};sprintf(testbuf, "%02X", (unsigned char)testc);