青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

loop_in_codes

低調做技術__歡迎移步我的獨立博客 codemaro.com 微博 kevinlynx

多線程下vc2003,vc2005對虛函數表處理的BUG?

考慮一下多線程代碼,在設計上,App為了獲取更多的功能,從Window派生,而App同時為了獲取
某個模塊的回調(所謂的Listener),App同時派生Listener,并將自己的指針交給另一個模塊,
另一個模塊通過該指針多態回調到App的實現(對Listener規定的接口的implemention)。設計上
只是一個很簡單的Listener回調,在單線程模式下一切都很正常(后面我會羅列代碼),但是換到
多線程下,編譯器似乎就對語言機制的支持不夠了:

///
/// to demonstrate the fucking bug.
///

#include <iostream>
#include 
<process.h>
#include 
<windows.h>

class Window
{
public:
    
/// 
    virtual void wrong()
    
{
        std::cout 
<< "wrong" << std::endl;
    }


    
virtual ~Window()
    
{
        std::cout 
<< "~Window" << std::endl;
    }

}
;


class Listener
{
public:
    
/// as most listener class, it only put some interface here
    virtual void show() {}
}
;

class Game
{
public:
    Game() : _listener( 
0 ) { }

    
void init( Listener *listener )
    
{
        _listener 
= listener;
        
/// it will call Window::wrong function but not App::show.
        _listener->show();
    }


private:
    Listener 
*_listener;
}
;

Game gGame;

static unsigned int __stdcall ThreadFunc( void *p )
{
    Listener 
*listener = (Listener*) p;
    gGame.init( listener );

    
whiletrue )
    
{
        std::cout 
<< ".";
        Sleep( 
100 );
    }


    _endthreadex( 
0 );
    
return 0;
}


class App : public Window, public Listener
{
public:
    
void init()
    
{
        
// create the game thread
        _game_thread = (HANDLE)_beginthreadex( NULL, 0, ThreadFunc, this0, NULL );
    }


    
/// implement the interface
    void show()
    
{
        std::cout 
<< "App::show" << std::endl;
    }


    
/// exit
    void exit()
    
{
        
/// just for testing purpose
        ::TerminateThread( _game_thread, 1 );
        ::CloseHandle( _game_thread );
    }


private:
    HANDLE _game_thread;
}
;


App gApp;


int main()
{
    gApp.init();

    std::cout 
<< "Press enter key to exit!" << std::endl;
    std::cin.
get();

    gApp.exit();
    
return 0;
}

 

App多重繼承Window和Listener,在Game里回調App::show時,卻調用到了Window::wrong函數。看上去,傳給
Game的Listener指針所指向的虛函數表錯誤了(vtable指針錯了)。App先繼承Listener后繼承Window時,情況
就正確了。(因為使用了_beginthreadex,程序需要鏈接多線程的運行時庫)

單線程情況下:

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// to demonstrate the fucking bug.
///
/// OK, even it links the multi-thread crt.

#include <iostream>
#include 
"kl_thread.h"

class Window
{
public:
    
/// 
    virtual ~Window()
    
{
        std::cout 
<< "~Window" << std::endl;
    }

}
;


class Listener
{
public:
    
/// as most listener class, it only put some interface here
    virtual void show() {}
}
;

/// 
Listener *gListener;

class App : public Window, public Listener
//class App : public Listener, public Base
{
public:
    
void init()
    
{
        gListener 
= this;
    }


    
/// implement the interface
    void show()
    
{
        std::cout 
<< "App::show" << std::endl;
    }

}
;


App gApp;


int main()
{
    gApp.init();

    gListener
->show();
    
return 0;
}

 

無論Listener, Window的順序如何,一切都很正常。這起碼說明了,在語言層次,我的做法是正確的。
而這個時候即使鏈接了多線程的運行時庫,結果也是正確的。

那么錯誤可以歸結于多線程,可能是在多線程下編譯器對虛函數表初始化不正確所致。這是否真的是
VC2003、VC2005的BUG?

 

posted on 2008-04-24 14:40 Kevin Lynx 閱讀(3839) 評論(12)  編輯 收藏 引用 所屬分類: c/c++

評論

# re: 多線程下vc2003,vc2005對虛函數表處理的BUG? 2008-04-24 16:09 Fox

還是寫出來看的清楚:static unsigned int __stdcall ThreadFunc( void *p )
{
Listener *listener = (Listener*) p;


應該是
Listener *listener = (App*) p;
  回復  更多評論   

# re: 多線程下vc2003,vc2005對虛函數表處理的BUG? 2008-04-24 17:34 giscn

或者這樣
_game_thread = (HANDLE)_beginthreadex( NULL, 0, ThreadFunc, (Listener*)this, 0, NULL );  回復  更多評論   

# re: 多線程下vc2003,vc2005對虛函數表處理的BUG? 2008-04-24 17:40 giscn

錯誤由void* 指針轉換引起,與多線程無關,C++ 的指針轉換不同于C, 如果是多集繼承,參數同樣是 this, 其實際值不一定相同,取決于參數類型  回復  更多評論   

# re: 多線程下vc2003,vc2005對虛函數表處理的BUG? 2008-04-24 17:40 eXile

樓上的正解。在使用多重繼承時要注意對象的布局。  回復  更多評論   

# re: 多線程下vc2003,vc2005對虛函數表處理的BUG? 2008-04-24 18:09 亨德列克

Listener *listener = (Listener*) p; 是這一行錯了,這個錯誤應該很多人都會犯……  回復  更多評論   

# re: 多線程下vc2003,vc2005對虛函數表處理的BUG? 2008-04-24 19:18 Kevin Lynx

@亨德列克
不是那一行錯了,App和Game兩個類分屬不同模塊,為了不讓兩個模塊耦合,這里使用Listener *listener = (Listener*) p,而不是(App*)p。

giscn和eXile (他刪除了他的第二條評論:) )的方法是正確的。可以被采用,再次表示感謝。

這讓我意識到,void*在C++里缺乏安全性。  回復  更多評論   

# re: 多線程下vc2003,vc2005對虛函數表處理的BUG? 2008-04-24 22:49 飯中淹

這不是多線程的問題

當你先繼承window后繼承Listener的時候,App的內存結構如下:

class App
vt of Window
data of Window
vt of Listener
data of Listener
data of App

_beginthreadex的參數是void*,你把this傳遞進去,相當于傳遞CApp* this。其實隱含的就是Window*this,那么里面調用Listener->Show,自然就會去Window的vt里面查找對應索引的函數,就會調用錯函數。

而第二個,因為你顯式的=this,所以,編譯器會進行轉換,從而把正確的Listener地址賦值給那個全局指針,這時,無論繼承順序如何,都是正確的結果。

這其實是因為對象指針轉換不準確導致的,不是vc的bug,也不是多線程的問題。
  回復  更多評論   

# re: 多線程下vc2003,vc2005對虛函數表處理的BUG? 2008-04-25 08:32 FongLuo

收藏,收藏,^_^  回復  更多評論   

# re: 多線程下vc2003,vc2005對虛函數表處理的BUG? 2008-04-25 17:03 #Ant

多繼承下還有這樣的問題,學習了。。。  回復  更多評論   

# re: 多線程下vc2003,vc2005對虛函數表處理的BUG?[未登錄] 2008-04-26 00:49 楊粼波

指針偏移,多線程會發生這樣滴問題。。。。  回復  更多評論   

# re: 多線程下vc2003,vc2005對虛函數表處理的BUG? 2008-05-12 09:33 hellfire

范仲淹的是正解哦,建議看看inside c++ object model. c++是一種和底層結合很緊密的語言。  回復  更多評論   

# re: 多線程下vc2003,vc2005對虛函數表處理的BUG? 2008-09-18 15:07 littlewater

純粹從本CPP來考慮
public Window, public Listener 換為:
public Listener, public Window 就是:
::
Press enter key to exit!App::show
.
..............
~Window

不過并不理想,因為不能夠轉換到Window的接口了  回復  更多評論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲综合精品四区| 精久久久久久久久久久| aa亚洲婷婷| 亚洲国产高清自拍| 看欧美日韩国产| 猛男gaygay欧美视频| 欧美激情成人在线| 亚洲欧洲偷拍精品| 日韩一级免费| 一本久久综合亚洲鲁鲁五月天| 一区二区三区精品久久久| 亚洲永久免费av| 久久久精品欧美丰满| 欧美.www| 日韩视频中午一区| 午夜视频一区| 欧美成人激情在线| 国产精品久久久久久久久久三级| 国产欧美日韩在线观看| 尤物yw午夜国产精品视频明星| 亚洲精品久久久久久下一站 | 午夜久久99| 久久天堂成人| 国产精品v欧美精品v日韩 | 国产精品影院在线观看| 国产欧美一区二区精品性色 | 亚洲裸体俱乐部裸体舞表演av| 一区二区三区免费观看| 欧美在线1区| 亚洲国产精品va在看黑人| 一区二区三区四区蜜桃| 校园春色国产精品| 欧美精品v日韩精品v韩国精品v | 欧美日韩综合视频网址| 欧美手机在线| 国产一区二区三区无遮挡| 一区二区三区高清在线| 久久夜色精品国产亚洲aⅴ| 亚洲精品影院在线观看| 欧美与欧洲交xxxx免费观看| 欧美激情中文不卡| 国产精品一级久久久| 亚洲久久在线| 久久亚洲不卡| 欧美一区二区大片| 国产精品国产三级国产专区53 | 在线亚洲美日韩| 欧美1区免费| 欧美一区二区三区视频在线观看| 欧美福利精品| 一区二区在线不卡| 欧美一区二区视频在线| 亚洲精品日韩激情在线电影| 久久久亚洲高清| 亚洲免费综合| 国产精品激情| 亚洲性感激情| 欧美国产亚洲另类动漫| 欧美一区网站| 国产美女精品人人做人人爽| 一区二区三区视频在线观看| 欧美.www| 久久综合亚洲社区| 韩国欧美一区| 免费h精品视频在线播放| 久久精品亚洲国产奇米99| 国产一区 二区 三区一级| 亚洲欧美日韩国产一区| 亚洲欧美日韩高清| 国产日本欧美在线观看| 久久国产欧美日韩精品| 亚洲自拍电影| 国产欧美视频一区二区| 久久乐国产精品| 久久久亚洲影院你懂的| 亚洲经典三级| 亚洲国产视频a| 欧美韩日高清| 亚洲午夜精品久久| 西西人体一区二区| 国内免费精品永久在线视频| 欧美成人国产| 欧美天堂亚洲电影院在线播放| 亚洲一区精品视频| 欧美在线3区| 亚洲欧洲三级| 99一区二区| 国产一区亚洲一区| 91久久亚洲| 国产精品乱码久久久久久| 玖玖玖国产精品| 毛片一区二区三区| 亚洲欧美www| 久久精品一区四区| 在线亚洲精品| 久久久www成人免费无遮挡大片 | 久久人人97超碰精品888| 老色鬼精品视频在线观看播放| 亚洲美女黄色片| 欧美尤物巨大精品爽| 日韩视频一区二区在线观看| 一本到12不卡视频在线dvd| 韩国av一区二区三区在线观看| 欧美激情中文字幕在线| 国产精品日韩一区二区三区| 蜜臀91精品一区二区三区| 欧美日韩国产综合一区二区| 久久婷婷色综合| 欧美视频手机在线| 欧美国产一区二区| 国产午夜一区二区三区| 亚洲精品系列| 尤物在线精品| 在线观看精品| 亚洲在线1234| 美玉足脚交一区二区三区图片| 亚洲天堂成人在线视频| 久久久久国产精品一区| 亚洲直播在线一区| 欧美精品日韩一本| 欧美成人黄色小视频| 国产亚洲欧美一级| 亚洲视频你懂的| 一区二区精品在线| 欧美xxx在线观看| 欧美1区3d| 很黄很黄激情成人| 欧美在线免费视频| 亚洲欧美电影在线观看| 欧美人与禽性xxxxx杂性| 欧美成人首页| 亚洲国产精品999| 久久久亚洲国产天美传媒修理工| 欧美一级日韩一级| 国产欧美综合一区二区三区| 亚洲影院免费观看| 欧美亚洲视频一区二区| 国产精品久久久免费| 日韩亚洲在线观看| 99re热精品| 欧美日韩精品欧美日韩精品 | 国产精品一区视频| 亚洲视频免费看| 亚洲欧美激情一区二区| 国产精品jizz在线观看美国| 亚洲精品乱码久久久久久蜜桃麻豆| 在线观看国产精品网站| 欧美诱惑福利视频| 老牛影视一区二区三区| 一区二区三区在线免费播放| 久久久久久久久久看片| 久久久成人精品| 国模精品一区二区三区| 久久久欧美精品| 欧美福利视频在线| 一本色道久久综合亚洲精品按摩 | 久久成人精品无人区| 国产亚洲二区| 免费在线欧美黄色| 亚洲精品资源| 欧美一区二区三区电影在线观看| 欧美日韩国产精品自在自线| 一区二区日韩| 久久久亚洲一区| 1024亚洲| 欧美日韩国产小视频| 亚洲一二三区精品| 久久亚洲国产精品一区二区 | 亚洲国产成人精品女人久久久 | 亚洲欧美制服中文字幕| 国产精品v欧美精品v日本精品动漫| 亚洲四色影视在线观看| 亚洲日本中文字幕| 国产精品视屏| 欧美在线首页| 亚洲大片在线观看| 亚洲网站在线看| 在线不卡a资源高清| 乱中年女人伦av一区二区| 亚洲精品色图| 久久综合久久久| 亚洲精品黄网在线观看| 欧美午夜视频| 久热爱精品视频线路一| 9色国产精品| 免费久久99精品国产自| 亚洲图片欧洲图片日韩av| 激情久久影院| 欧美日韩免费观看一区| 久久久久久久尹人综合网亚洲| 亚洲第一精品夜夜躁人人爽| 香蕉成人久久| 亚洲精品久久久久久一区二区| 国产精品欧美一区喷水| 欧美xart系列高清| 欧美在线一二三区| 亚洲区一区二区三区| 久久久精品日韩欧美| 亚洲欧美另类在线| 亚洲最快最全在线视频|