Bug:C++運行時調用純虛函數

來源:互聯網
上載者:User

標籤:nbsp   跳過   ica   記錄   使用   解構函式   lin   服務   print   

    昨天伺服器宕機,列印出的日誌非常詭異,宕在純虛函數調用處。
    日誌顯示,戰鬥對象的虛函數調用,前幾次正常,某個時刻過後“喪失多態”了,直接調到父類虛函數處,引發純虛函數宕機。
    且win平台下運行正常,上linux必跪,老項目linux工具不全,debug版本都編不出來,只有Log;windows下還複現不出來。

    找這個bug的過程還是蠻有意思的。記錄下(*^__^*)     

    以往沒碰到過這種Bug,起初當然毫無頭緒。
    首先想到,c++中經常的記憶體改寫,但能正常調用到普通虛函數,應該不是memset這樣的東西把對象寫壞。
    進一步分析,要能正常調到父類虛函數,那對象虛指標一定指向了正確的父類虛表。

    回憶c++建構函式流程:
        1、假設CBase裡有幾個純虛函數 CObj 繼承它
        2 、CObj 的構造順序:先構造 CBase 的部分,此時對象首地址的虛指標指向了 CBase的虛表……再接著構造 CObj 新增的部分,改寫對象首地址的虛指標,指向ClassObj的虛表

    如果解構函式按對應順序反過來,容器裡儲存的 CBase* 指標,經過析構後,指向的對象,它的首地址就被改寫為指向 CBase 虛表了。

    這樣就會出現日誌看到的情況。

    但我不確定解構函式是不是會改虛指標,按照構造、析構對稱的思路預計是會的。
    網上也沒查到資料,決定寫代碼實驗~~結果不會
    …………沒啥線索了

    晚上想起編譯器對拷貝建構函式的最佳化,預設產生的拷貝建構函式其實不會被調用(沒有副作用),直接最佳化為位元組拷貝即可。
    寫的測試代碼裡沒顯式聲明解構函式,會不會也被編譯器跳過了。所以 delete 後,首地址的vptr還是沒變。

    今天來立馬改了測試代碼,在父類裡加上解構函式聲明、實現……果然,析構後對象首地址的內容被改寫了
    Obj* pB = new Obj();    printf("addr(%d) \n", *((int*)pB));    delete pB;    printf("addr(%d) \n", *((int*)pB));

    至此,可以肯定伺服器宕機,就是因為戰鬥對象被析構,虛指標被改寫為指向父類虛表,業務層再拿來用時就跪了。
    (因為用到記憶體池,所以沒出現懸垂指標的問題) 

    剩下的就好查了,delete對象時某業務模組仍持有其指標,沒清理。搜搜戰鬥對象的參考關聯性,幾分鐘便找到問題所在。
        戰鬥城池裡有個守衛列表,npc進入時會把自己指標放入這個列表,死亡時沒去清。    別人再來打這個城池時,跑戰鬥流程就調了純虛函數,宕機。
    
尾聲:
    覺得這個bug挺有深度的,能扣的地方很多。
    比如,為什麼在win下不會宕機呢?項目裡的戰鬥對象也是沒顯式解構函式的,應該是被vs編譯器最佳化掉了,而Linux沒有。
    再比如,如果沒有記憶體池,那兩邊應該都會出現懸垂指標,直接宕機……提前暴露問題所在,反而更好分析定位Bug。
    還有,win環境下,即便免去了純虛函數的宕機問題,但確將Bug隱藏的更深了。後面商務邏輯再從記憶體池取指標,拿到那箇舊的,胡亂一改,再出問題時候,你看到的就是一坨shit了,鬼知道到底是哪改壞的 ( ̄﹁ ̄)~

    還是我們老大說的好:
        記憶體池如果是新項目,我估計不會使用,會直接用TCMALLOC之類的。我還是想能工程化就工程化,C++開發還是要往庫的思維走。不然老挖坑填坑。


PS: 沒頭緒下班前,我幹了三件事情:
                在前C++項目群裡描述問題,詢問“有誰碰到過中途調純虛函數,伺服器宕機的情況”;
                在加入的技術群裡問;
                在知乎提問,邀請輪子哥、R大
        次天來就看到有人回複:子類析構掉的話,虛表會被改寫成iobj的虛表,析構過的指標,可以調iobj的虛函數,調其它虛函數則會掛
        即使自己沒能想到“析構過程可能被編譯器最佳化掉”,也能在他們的指導之下找到問題的。
        利用別人的經驗哈 b( ̄▽ ̄)d

Bug:C++運行時調用純虛函數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.