C++強制轉換不同聲明或類型的函數指針隱患

之前碰到一個問題,沒有注意看函數指針的定義。造成一個錯誤,寫到這裏給自己一個提醒。也給大家看看我這個不小心的人犯的錯誤。嘿嘿!

 

先看段測試代碼:

void test( int param )
{
     int ret = 0;
     for ( int i = 0; i < param; ++i )
     {
      ret += i;
     }

     ret >>= 16;
     ret |= ( ret << 16 );
}

 

typedef bool ( *PFUNC )( int args );

int main( void )
{
     PFUNC Func;
     Func = ( PFUNC )test;

     if ( Func( 200 ) )
    {
         cout << "good" << endl;
    }
    else
     {
          cout << "bad" << endl;
     }

     return 0;
}

 

這段代碼裏面,我故意把test函數裏面的內容多寫幾步,讓它有“效果”。在遊戲程序裏面,一個函數可能有很多的語句,這裏只是簡單演示下我的錯誤- -。 我們的函數指針聲明是:

typedef bool ( *PFUNC )( int args );

它指向的是返回值爲bool,參數爲int類型的函數。而我定義的test函數是沒有返回值的。來看看程序輸出會是什麼。

這裏可以說,輸出的結果是未知的。因爲不知道Func( 200 )的返回值是多少。可能有的朋友會疑問,這裏的test函數不是沒有返回值嗎?

 

這裏就要牽涉到彙編層面我們的返回值如果是在32位以內的話,都會放到eax裏面。我們沒有返回值,而通過強制類型轉換。這裏能通過編譯了。但是在test函數結束時,eax寄存器裏面的值是不確定的。當我們判斷

if ( Func( 200 ) )這個條件也就是不確定的。在遊戲程序中,這樣的錯誤是不允許的。也可以說是嚴重的。

 

可能也有朋友會問爲什麼EAX的值是不確定的呢? 因爲eax是通用寄存器,在函數內部,它通常用來保存一些臨時值。所以改變的因素就很大。不確定性也就很大。

看看test的調試版本反彙編代碼:

test:
004170B0  push        ebp 
004170B1  mov         ebp,esp
004170B3  sub         esp,0D8h
004170B9  push        ebx 
004170BA  push        esi 
004170BB  push        edi 
004170BC  lea         edi,[ebp-0D8h]
004170C2  mov         ecx,36h
004170C7  mov         eax,0CCCCCCCCh
004170CC  rep stos    dword ptr [edi]
004170CE  mov         dword ptr [ret],0
004170D5  mov         dword ptr [i],0
004170DC  jmp         test+37h (4170E7h)
004170DE  mov         eax,dword ptr [i]
004170E1  add         eax,1
004170E4  mov         dword ptr [i],eax
004170E7  mov         eax,dword ptr [i]
004170EA  cmp         eax,dword ptr [param]
004170ED  jge         test+4Ah (4170FAh)
004170EF  mov         eax,dword ptr [ret]
004170F2  add         eax,dword ptr [i]
004170F5  mov         dword ptr [ret],eax
004170F8  jmp         test+2Eh (4170DEh)
004170FA  mov         eax,dword ptr [ret]
004170FD  sar         eax,10h
00417100  mov         dword ptr [ret],eax
00417103  mov         eax,dword ptr [ret]
00417106  shl         eax,10h
00417109  or          eax,dword ptr [ret]
0041710C  mov         dword ptr [ret],eax
0041710F  pop         edi 
00417110  pop         esi 
00417111  pop         ebx 
00417112  mov         esp,ebp
00417114  pop         ebp 
00417115  ret    

 

改變eax的地方我已經標註爲紅色,我們能準確知道最後改變後的eax的值嗎? 主函數裏面還等着這個eax的值呢 - -

答案是不能,況且在複雜的遊戲服務器程序中。這裏只是單是返回值不同。還有參數不同的強制類型轉換,參數和返回值都不同的強制類型轉換。這種不小心的操作,很可能導致程序越界,溢出等而崩潰。

希望大家不要像我這麼粗心哈。 嘿嘿。睡覺。。真睡了- -

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章