首页
社区
课程
招聘
[注意]Interlocked函数和编译器BUG产生的错误
发表于: 2015-6-10 08:49 4576

[注意]Interlocked函数和编译器BUG产生的错误

2015-6-10 08:49
4576
不确定是不是编译器BUG

调试Wrk的时候 出现了BUG, 模拟测试函数如下 调用了一下InterLockedOr

void TestFunc()
{
        LONG TestFlag = 1;
        if (!InterlockedOr(&TestFlag,1))
        {
                DbgPrint("Test Flag = 0\n");
        }
        else
        {
                DbgPrint("Test Flag = 1\n");
        }
}
输出结果是错误的 Test Flag = 0
InterlockedOr返回值是原来的值 也就是TestFlag=1; !1=0;应该执行的是 else的语句

反汇编代码如下

808688d6 55              push    ebp
808688d7 8bec            mov     ebp,esp
808688d9 51              push    ecx
808688da 33c0            xor     eax,eax
808688dc 40              inc     eax
808688dd 56              push    esi
808688de 8945fc          mov     dword ptr [ebp-4],eax
808688e1 8bc8            mov     ecx,eax
808688e3 8d55fc          lea     edx,[ebp-4]
808688e6 8b02            mov     eax,dword ptr [edx]
808688e8 8bf0            mov     esi,eax
808688ea 0bf1            or      esi,ecx
808688ec f00fb132        lock cmpxchg dword ptr [edx],esi
808688f0 75f6            jne     nt!TestFunc+0x12 (808688e8)
808688f2 5e              pop     esi
808688f3 7507            jne     nt!TestFunc+0x26 (808688fc)
808688f5 68b6888680      push    offset nt!ObpIsUnsecureName+0x5a (808688b6) Test Flag=0;
808688fa eb05            jmp     nt!TestFunc+0x2b (80868901)
808688fc 68c6888680      push    offset nt!ObpIsUnsecureName+0x6a (808688c6) Test Flag=1;
80868901 e84a96ffff      call    nt!DbgPrint (80861f50)
80868906 59              pop     ecx
80868907 c9              leave
80868908 c3              ret


808688f0
808688f3  两个JNE是同样的结果 POP ESI 不改变标志位。

[edx]=eax=ecx=esi=1;
or esi,ecx
esi=1
lock cmpxchg dword ptr [edx],esi  esi=[edx]=1;
jne都不跳 也就输出了 Test Flag=0;

WRK内置的编译器cl是2003的版本
特意下了个VS2003 然后控制台测试并没有发现这个问题,不知道是哪里的问题。
GOOGLE一下
原来我不是第一个发现这个问题的
http://www.osronline.com/showThread.cfm?link=92466

注意注意,这个问题调试WRK搞了我一天。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 1392
活跃值: (5207)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
2
望大神解释~~
2015-6-10 08:50
0
雪    币: 272
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
是不是编译时没关优化选项?你看808688f0的转跳,跳到上面去循环了,以前的某个优化bug也是这样
2015-6-10 14:45
0
雪    币: 65
活跃值: (112)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
建议准确、清楚地看msdn关于interlockedXXX系列函数的说明,理解什么叫volatile
2015-6-10 14:50
0
雪    币: 1392
活跃值: (5207)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
5
这个Jmp 不是优化BUG,InterLockedOr内部实现是这样

LONG InterlockedOr(LONG* Variable, LONG OrVal) 
{ 
LONG OldVal;
 LONG NewVal;
    for(;;) 
   {
      OldVal = *Variable;
      NewVal = OldVal | OrVal;
      if( InterlockedCompareExchange(Variable, NewVal, OldVal) == OldVal )
                 break; 
   } 
   return OldVal; 
}

所以会需要跳上去,这里应该没什么问题。
2015-6-10 17:05
0
雪    币: 1392
活跃值: (5207)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
6
先不说 是不是优化造成,或者指定一个变量val=InterlockedOr 申明不可优化。至少逻辑上应该是对的,不管优不优化,逻辑不应该改变。
2015-6-10 17:12
0
雪    币: 272
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
看汇编代码,明显被内联展开了,肯定是用的优化选项,关掉试试。
2015-6-11 03:00
0
游客
登录 | 注册 方可回帖
返回
//