2008-11-19 53 views
4

假設一個人已經繼承了一個複雜的代碼庫(在Visual C++中,假設爲2003年或者更晚的版本),並帶有一個龐大而複雜的繼承圖。假設它很深,並且有很多虛函數,甚至可能有多重繼承。 (是的,有點維修的噩夢)。任何試圖將這個類層次結構重構爲更精確的東西都需要知道每個類使用的每個虛函數的實現。如何檢查Visual C++中的vtable?

如果我們取一個任意的葉類L1 - 它派生自基類B1,它派生自基類B2,等等 - 它顯然會有一個類的虛表,它將顯示類似於(僞虛表):

L1::F1 
B3::F2 
B1::F3 
L1::F4 
etc. 

...取決於具體哪個虛擬函數被哪個類所覆蓋。

怎麼能看到這樣一個虛擬桌面形式很像這樣?通過閱讀代碼可以手工重構,但這很容易出錯並且很費力。據推測,在調試器中闖入類的對象可能允許您通過該類的vtable指針在Watch窗口中檢查vtable,但這是一個尷尬的解決方案,特別是如果您還想查看L2的vtable, L3,... LN。

DbgHelp.dll是否提供了以編程方式檢查vtables的功能(允許以任何形式輸出)?或者還有其他一些方法嗎?

回答

14

使用Visual Studio 2005,有兩個未記錄的標誌可以完全滿足您的需求。他們是報告所有類別佈局報告單個類佈局標誌。例如,在cl.exe命令行上嘗試「/ d1 reportAllClassLayout」。它會顯示完整的課程佈局,包括虛擬表格,這裏有一個Example。另請參閱http://blogs.msdn.com/vcblog/archive/2007/05/17/diagnosing-hidden-odr-violations-in-visual-c-and-fixing-lnk2022.aspx這些標誌沒有太多的信息,因爲它們現在沒有記錄,但也許Microsoft將在未來版本的Visual Studio中正式支持它們。

另一種方法,實際上我更喜歡使用IDA Pro交互式反彙編程序。有一個巨大的學習曲線,但IDA足夠聰明,可以幫助您構建VTable並將它們鏈接到您的課程。它用於反向工程,你沒有傳統的符號,但它也使用Visual Studio pdb文件。這樣做你會看到正好什麼所有你的虛擬桌面看起來像。哪些虛擬表正在用於哪些方法,或哪些方法被覆蓋,同時逐步完成代碼。換句話說,在運行時調試期間,您實際上會看到您的方法調用被跟蹤到到vtable中。像VS調試器這樣的典型調試器不會像您注意到的那樣追蹤到虛擬表中。

1

我強烈推薦使用Doxygen作爲任何類型的代碼分析工具。我不認爲它有一種快速的方法來查找類型中任何函數的最終覆蓋,但它應該提供一個繼承和實現的列表,以便您可以快速掃描該樹以識別覆蓋任何給定的函數(通常,您的層次結構不夠大以至於無法實現)。它還可以生成調用圖,關係圖和超鏈接源代碼,這是一個非常棒的工具。