2012-03-13 162 views
1

我正在調試商業軟件的插件。按下退出按鈕後,應用程序崩潰。這些崩潰出現在windows vista 64 sp2或vista 32(不記得是否是sp),但不在windows xp sp3上。根據應用程序生成的崩潰日誌,看起來我有一些堆問題,所以我使用頁堆激活進行調試。未執行代碼崩潰

幾乎從頭開始,我採用了一個插件示例代碼,在該代碼中逐漸添加我的代碼。我的插件添加了一個創建我的工具的按鈕。該工具和按鈕是兩個獨立的COM對象。該按鈕始終創建,但只有按下按鈕才能創建工具對象。 現在,我在工具部分添加了一些代碼,代碼沒有執行,工具對象甚至沒有創建,但程序崩潰。沒有這部分代碼,它不會。它似乎不依賴於代碼的那部分,當我評論它並在其他地方添加一些代碼(不會執行)時,程序崩潰的方式相同。

ADPlus的告訴我:損壞堆指針或使用錯誤的堆 XX:堆在呼叫 XX使用:堆塊 XX:塊大小 XX:堆擁有該塊

任何想法或調試策略我可以開始嗎?

謝謝。

+0

一些代碼會很有用。一個簡單的repro案例。 – Robinson 2012-03-13 18:58:45

回答

0

給代碼示例總是有幫助。

堆損壞真的很棘手,因爲即使它是錯誤的,它可能不會被檢測到。所以雖然你可能會以某種方式持續發生崩潰,但這並不意味着當你沒有崩潰時它不會崩潰。

由於靜態初始化,崩潰而不能連接是合理的。我會嘗試在連接DLL時手動初始化這些類型的資源。在DLL分離時刪除資源,並將指針設置爲零。有「主要」靜態函數來處理這個,你可以進入。

您也可能會對靜態的初始化順序做出假設,但這並不是毫無保證的。更糟糕的是,他們會長時間表現相對一致,然後出於某種原因而看似隨機的時間突然出現,這一點並不明顯。

COM對象的另一種可能性是您的二進制兼容性不再匹配調用代碼所期望的接口。如果您正在實現的界面不是PURE虛擬的,這可能是特別意外的。如果接口具有默認實現的任何方法,則需要覆蓋它們。

struct foo_base { 
    virtual ~foo_base() {} 
    virtual std::string getName() const { 
    return "Willem Dafoe"; 
    } 
}; 

struct foo_derived : public foo_base { 
    virtual ~foo_derived() {} 
}; 

即使這是完全有效的C++,它可能無法用作COM對象。

如果您對血腥細節不感興趣,請爲虛擬方法添加一個實現,該虛擬方法只需調用基礎。

struct foo_base { 
    virtual ~foo_base() {} 
    virtual std::string getName() const { 
    return "Willem Dafoe"; 
    } 
}; 

struct foo_derived : public foo_base { 
    virtual ~foo_derived() {} 
    virtual std::string getName() const { 
    return foo_base::getName(); 
    } 
}; 

我從來沒有見過從這個人的堆腐敗消息,但我看到它調用垃圾指針的方法。如果您試圖釋放它,我可以看到可能被檢測爲堆損壞。