如何在 Visual C++ 中检查 vtable?
Posted
技术标签:
【中文标题】如何在 Visual C++ 中检查 vtable?【英文标题】:How can one inspect a vtable in Visual C++? 【发布时间】:2008-11-19 16:18:59 【问题描述】:假设一个人继承了一个复杂的代码库(在 Visual C++ 中,假设是 2003 年或更晚),并带有一个大而复杂的继承图。假设它很深,并且有很多虚函数,甚至可能还有多重继承。 (是的,有点维护噩梦)。任何将这个类层次结构重构为更合理的东西的尝试都需要知道每个类使用的每个虚函数的实现。
如果我们采用任意叶类 L1 - 它派生自基类 B1,而基类 B2 派生自基类 B2 等等 - 它显然会为该类提供一个 vtable,它将显示类似(伪 vtable)的内容:
L1::F1
B3::F2
B1::F3
L1::F4
etc.
...具体取决于哪些虚函数已被哪个类覆盖。
人们怎么能以类似的形式看到这样的 vtable?可以通过阅读代码手动重建它,但这容易出错且费力。据推测,在调试器中闯入类的对象可以允许您通过该类的 vtable 指针在 Watch 窗口中检查 vtable,但这是一个尴尬的解决方案,特别是如果您还想查看 L2 的 vtable, L3, ... LN。
DbgHelp.dll 是否提供了以编程方式检查 vtable 的工具(允许以任何需要的形式输出)?还是有其他方法?
【问题讨论】:
【参考方案1】:在 Visual Studio 2005 中,有两个未记录的标志可以完全满足您的需要。它们是 reportAllClassLayout 和 reportSingleClassLayout 标志。例如,在 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这些标志的信息并不多,因为它们目前没有文档记录,但也许微软会在未来版本的 Visual Studio 中正式支持它们。
另一种方法,实际上是我更喜欢的方法,是使用IDA Pro 交互式反汇编程序。有一个巨大的学习曲线,但 IDA 足够聪明,可以帮助您构建 VTable 并将它们链接到您的类。它用于对传统上没有符号的二进制文件进行逆向工程,但它也使用 Visual Studio pdb 文件。这样做您将确切地看到您的 vtable 的所有是什么样的。哪些虚拟表被用于哪些方法,或者哪些方法被覆盖,所有这些都是在单步执行代码时进行的。换句话说,您实际上会在运行时调试期间看到您的方法调用被跟踪到 vtable 中。如您所见,VS 调试器等典型调试器不会跟踪到虚拟表。
【讨论】:
【参考方案2】:我强烈建议使用Doxygen 作为任何类型的代码分析工具。我认为它没有快速找到类型中任何函数的最终覆盖器的方法,但它应该提供继承和实现的列表,以便您可以快速扫描树以识别覆盖器任何给定的功能(通常,您的层次结构不足以使其成为大问题)。它还可以生成调用图、关系图和超链接源代码,这是一个很棒的工具。
【讨论】:
以上是关于如何在 Visual C++ 中检查 vtable?的主要内容,如果未能解决你的问题,请参考以下文章
如何检查是不是在 Visual C++ 应用程序中的第三方 DLL 中创建了新线程