我從一個3-Pary庫龐大類的工作,這裏是相關的東西摘錄:如何調試在Visual Studio中的錯誤調用堆棧
class SomeClass {
// ...
public:
// ...
virtual int SetTableSize(unsigned int uiTableID, int iSize);
// ...
protected:
// ...
virtual int Set_0xB0_0x23_IsoTableData(unsigned char* ucData, int iLen);
// ...
};
我的應用程序中斷與內存訪問衝突。在調用堆棧最上面的項目是在Set_0xB0_0x23_IsoTableData
執行情況的代碼行,第二項是代碼行是這樣的:
someClassInstance.SetTableSize(2, 400);
在調試視圖,ucData
具有價值0x00000002
,所以纔像代替根據代碼調用SetTableSize
的實現,Set_0xB0_0x23_IsoTableData
被調用指定的參數 - 這顯然會導致錯誤,因爲指針是無效的。
我已經花了很多時間弄清楚這裏發生了什麼。我在Linux上使用GCC在不同的應用程序中編譯相同的代碼,並且它在那裏工作。這是一個Visual Studio編譯器錯誤?編譯此代碼時,我沒有收到任何警告。
不可能構建一個最小的工作示例來重現錯誤 - 至少直到我找出發生這種情況的原因爲止。 SomeClass
頭部確實有一些#ifdef
s,所以我首先想到的是,編譯包含SomeClass
的模塊時,預編譯器定義的編譯方式與編譯我的調用代碼時不同。但是,我仔細檢查,定義是相同的。
所以,我要問的是基本上是:
- 在什麼情況下可以對虛擬方法的調用調用另一個虛擬方法的實現? (這不是關於繼承 - 兩種方法是在同一類中定義的,甚至不共享其簽名並具有不同的可見性)
- 如何調試此類錯誤?是否有可能在Visual Studio中查看類實例的調度向量?
您可能已經破壞了堆棧,例如通過寫入緩衝區末尾或使用陳舊指針。不幸的是,這可能發生在遠離堆棧中的代碼的地方。 – molbdnilo
這是一個相當常見的模塊邊界問題。進行調用的代碼是使用該類的不兼容視圖構建的。可能是因爲您使用了使用不同版本的編譯器或標準C++庫構建的靜態庫。可能是一個DLL地獄問題。可以像調試和發佈版本一樣簡單。你的問題不包括這些事故。用完全相同的設置重建所有內容。 –
@HansPassant作爲我的解決方案的一部分,我已經從源代碼編譯第三方庫,並且該解決方案由CMake創建,它確保定義相同。 – flyx