我正在尝试修补一些用C ++编写的库代码。一个相当复杂的应用程序位于库的顶部。为了修补代码,我经常需要了解如何在整个代码库中使用库函数,并确保我没有破坏任何下游客户端。
假设从我的图书馆的dll导出foo()
。在客户端代码中,bar()
调用foo()
,baz()
调用bar()
。我需要确保bar
和baz
在我的更改后都能正常工作。在我的情况下,调用堆栈实际上非常深,并且不容易手动跟踪,因为没有一个调用堆栈,我的库函数可以通过多种方式落在调用堆栈的顶部。
使用Visual Studio,或g ++或clang,有一种生成树的方法,使我的库函数位于根,并且分支是我的函数可以在调用顶部着陆的各种方式堆?我的意思是这个功能在一个流行的工具链中是否已经存在?如果没有,你知道生成这样一棵树的其他方法吗?
答案 0 :(得分:1)
我认为任何编译器都没有选择来生成这些信息。
在一般情况下,有许多混淆因素会使这一点变得非常困难:
如果代码中有递归,那么您想要的树实际上是具有周期的图形/网络。
虚拟方法,函数指针和成员函数指针可能使这等同于暂停问题。如果您有两个具体的类A
和B
共享一个提供虚方法foo()
的公共基类,那么您必须进行详尽的分析以确定是否对{的特定调用{1}}通过指针或对基类的引用应被视为对foo()
或A::foo()
或两者的调用。同样适用于各种口味的功能指针。
如果您依赖可以回调代码的系统或其他第三方库,您最好拥有它们的来源。例如,Windows GUI程序通常具有从系统代码调用的窗口过程,可能是为了响应从代码到系统的调用。既然你不会拥有windows源代码,你必须假设任何时候都可以调用你的所有回调,因此你的“树”会有很多根。
解决这个问题的现代方法不是要分析你的库的所有调用方式,而是要记录它应该被调用的所有方式。构建一个测试套件,以您想要支持的所有合理方式调用库。然后你可以修补然后运行你的测试套件,看看你是否违反了图书馆的合同。如果在集成测试中,您发现库的客户端已被更改破坏,则表示测试套件不完整或客户端以不支持的方式调用库。