这算是VC6.0编译器的一个Bug么?
今天在VC6.0写下如下代码:
view plaincopy to clipboardprint?
#include
int bug()
{
int a=3,b;
b=(++a)+(++a)+(++a);
return b;
}
void main()
{
int b = bug();
printf("%d", b);
view plaincopy to clipboardprint?
#include
int bug()
{
int a=3,b;
b=(++a)+(++a)+(++a);
return b;
}
void main()
{
int b = bug();
printf("%d", b);
}
#include
int bug()
{
int a=3,b;
b=(++a)+(++a)+(++a);
return b;
}
void main()
{
int b = bug();
printf("%d", b);
}
首先看看我上面这段C代码,按照C语言的运算符优先级规则,这个程序的运行结果应该是18(首先执行完小括号里的三个++a,这时a就为6,然后在执行加法运算,3个a相加自然等于18)。
可是我在VC6.0下编译这段程序时,如果编译为Debug版,则输出结果为16,如果编译为Release版本,则输出结果为18。
为什么Debug版本的结果会是16呢???怎么想也不应该是16啊。于是自然就想到了看看这段程序对应Debug版的汇编代码吧,看看VC的编译器究竟把这段代码编译成什么样子了。为了简单起见,我只分析子函数bug()。
int a=3,b;
b=(++a)+(++a)+(++a);
以上这两行代码在VC的Debug版本下对应的汇编代码为:
0040102F 8B 45 FC mov eax,dword ptr [ebp-4]
00401032 83 C0 01 add eax,1
00401035 89 45 FC mov dword ptr [ebp-4],eax
00401038 8B 4D FC mov ecx,dword ptr [ebp-4]
0040103B 83 C1 01 add ecx,1
0040103E 89 4D FC mov dword ptr [ebp-4],ecx
00401041 8B 55 FC mov edx,dword ptr [ebp-4]
00401044 03 55 FC add edx,dword ptr [ebp-4]
00401047 8B 45 FC mov eax,dword ptr [ebp-4]
0040104A 83 C0 01 add eax,1
0040104D 89 45 FC mov dword ptr [ebp-4],eax
00401050 03 55 FC add edx,dword ptr [ebp-4]
00401053 89 55 F8 mov dword ptr [ebp-8],edx
上面这段汇编代码的意思,相信只要懂得汇编的朋友都可以很容易看懂,不过为了照顾一下大众,我还是简单说明一下吧,根据变量定义的位置可以知道,ebp-4就是变量a的地址,ebp-8就是变量b的地址,于是以上代码可以简化为:
mov eax,a
add eax,1
mov a,eax
//此时a=4
mov ecx,a
add ecx,1
mov a,ecx
//此时a=5
mov edx,a
add edx,a
//此时edx=10
mov eax,a
add eax,1
mov a,eax
//此时a=6
add edx,a
mov b,edx
//此时b=16
所以,最后的结果当然就是16啦。
随后我又用OD对Release版的程序进行了逆向分析,大家看图:
这个结果让我感到很意外,在Release版中,子函数bug()居然被优化成了直接返回结果:0x12(十进制就是18)。
至于其中为什么会优化成那样的原因我可就不知道了,这要去问问微软那些开发这个VC编译器(这里顺便一下:VC6.0自带的 C/C++编译器版本为:Version 12.00.8804)的工程师了,呵呵。当然也可以通过逆向分析这个VC编译器,从而找到答案,不过本人能力有限,目前还很难办到,若哪位大牛路过本站,还请不吝赐教,我的站点是www.。请大家来帮忙解决啊?????