我正在調試一個有害的內存損壞錯誤,它看起來像一個指向vtable
的指針正在被破壞。我想通過比較指針的值和指針的正確值(vtable
的真實位置)在我的程序中的不同位置來檢測它何時發生。有什麼直接的方法可以在編譯時獲得一個vtable的地址嗎?
不幸的是,我還沒有找到一種方法來在編譯時獲得指針的正確值,所以我不得不實例化一個新的對象,只是爲了讀取它的指針vtable
,這似乎是不必要的黑客行爲。
#include <iostream>
#include <iomanip>
#include <stdint.h>
class Foo {
virtual void performVirtualAction() {
std::cout << "Foo's version" << std::endl;
}
};
class Bar : public Foo {
virtual void performVirtualAction() {
std::cout << "Bar's version" << std::endl;
}
};
int main(){
Foo foo;
Bar bar;
std::cout << "Foo's vtable pointer " << std::hex << *(uint64_t*)(&foo) << std::endl;
std::cout << "Bar's vtable pointer " << std::hex << *(uint64_t*)(&bar) << std::endl;
}
是否有表達我想要的vtable
的特定類型像Foo
或Bar
位置的想法更直接的方式?
該方法不必是可移植的。它只適用於Linux上的gcc
。
我想在嘗試這種類型的黑客之前,你已經跑過'valgrind','asan','ubsan'嗎? –
我正在調試分佈式系統的部分。當我連接valgrind時,它改變了時間,所以我無法重現這個問題。我還沒有看到它聽到其他兩個,但會看看他們。 – merlin2011
我會有興趣知道問題是否真的是vtable腐敗。無論如何,大多數情況下,儘管依賴於編譯器,但vtable位於對象的開始位置 - 例如,這些對象是作爲示例使用的。 (例如,當它不在開始時:當基類沒有虛擬化時)。無論如何,你是否有權訪問一個堆,在調試模式下,可以通過在堆分配前後分配警戒來檢測超限? (MS VC++有這種功能。)它不應該干擾很多時間(假設你不在機器RAM容量附近)。 – davidbak