当前位置: 代码迷 >> VC >> 关于C++2005编译器的一个Bug。该怎么处理
  详细解决方案

关于C++2005编译器的一个Bug。该怎么处理

热度:6116   发布时间:2013-02-25 00:00:00.0
关于C++2005编译器的一个Bug。
关于C++2005编译器的一个Bug。

大家一起确认一下我说的是否正确,也讨论一下用什么好的方法来规避这个问题。
Contact me : chuyangguang@gmail.com 褚阳光

c++ 2005编译器在使用/clr选项时在一些特殊情况下会导致Release版本程序行为失常,产生错误的结果。
以下为示例程序:(项目类型为:VC ++ 2005的 CLR控制台应用程序)
#include "stdafx.h"
using namespace System;

typedef union
{
__int16 i;
unsigned __int16 ui;
} ALLTYPE;

void func(ALLTYPE *p);

int main(array<System::String ^> ^args)
{
ALLTYPE all;
all.ui = 32769;
func(&all);
Console::WriteLine("Press Enter to exit...");
Console::ReadLine();
return 0;
}

void func(ALLTYPE *p)
{
if(p->i == 0) //如果把这两行注释掉,
Console::WriteLine("0"); //则会正常工作。
if(p->ui == 32769)
Console::WriteLine("32769"); //func的函数体必须足够长,
else if(p->ui == 32770) //否则生成Release版本时会优化为inline函数。
Console::WriteLine("32770");
else if(p->ui == 32771)
Console::WriteLine("32771");
else if(p->ui == 32772)
Console::WriteLine("32772");
else if(p->ui == 32773)
Console::WriteLine("32773");
else if(p->ui == 32774)
Console::WriteLine("32774");
else if(p->ui == 32775)
Console::WriteLine("32775");
}
生成Release版本并运行,你会发现,程序的窗口中不会显示本应该有的32769。而Debug版本是能正常显示的。

问题出在Release版本的优化上。
来看Debug版本的汇编码如下: 

if(p->i == 0)  
00000000 push esi  
00000001 mov esi,ecx 
00000003 cmp dword ptr ds:[00C22DD8h],0 
0000000a je 00000011 
0000000c call 78E612A9 
00000011 cmp word ptr [esi],0 //判断 p->i == 0
00000015 jne 00000022 
Console::WriteLine("0");  
00000017 mov ecx,dword ptr ds:[023B3064h] 
0000001d call 7818BFA8 
if(p->ui == 32769)  
00000022 cmp word ptr [esi],8001h //判断 p->ui == 0
00000027 jne 00000037 
Console::WriteLine("32769");  
00000029 mov ecx,dword ptr ds:[023B3068h] 
0000002f call 7818BFA8 
00000034 nop  
00000035 jmp 000000B2 

上述汇编码没有使用优化处理,老老实实用 cmp word ptr操作,运行结果正常。

再看Release版本的汇编码:
if(p->i == 0)  
00000000 push edi  
00000001 push esi  
00000002 mov edi,ecx 
00000004 cmp dword ptr ds:[009E2DD8h],0 
0000000b je 00000012 
0000000d call 790A39D9 
00000012 xor esi,esi 
00000014 cmp word ptr [edi],0 //判断 p->i == 0
00000018 jne 00000025 
Console::WriteLine("0");  
0000001a mov ecx,dword ptr ds:[02193058h] 
00000020 call 783CE6D8 
if(p->ui == 32769)
00000025 movsx eax,word ptr [edi] //问题在这里,movsx指令
00000028 mov esi,eax //优化处理,把p->ui装入esi寄存器
0000002a cmp esi,8001h //比较结果为不相等!
00000030 jne 00000043 
Console::WriteLine("32769");  
00000032 mov ecx,dword ptr ds:[0219305Ch] 
00000038 call 783CE6D8 
0000003d nop  
0000003e jmp 000000C4 
else if(p->ui == 32770)  
00000043 cmp esi,8002h //优化后,后续比较直接使用esi寄存器的值
00000049 jne 00000059 
Console::WriteLine("32770");
0000004b mov ecx,dword ptr ds:[02193060h] 
  相关解决方案