生成所有可能的调用堆栈的树

时间:2017-01-06 17:12:20

标签: c++ dll callstack

我正在尝试修补一些用C ++编写的库代码。一个相当复杂的应用程序位于库的顶部。为了修补代码,我经常需要了解如何在整个代码库中使用库函数,并确保我没有破坏任何下游客户端。

假设从我的图书馆的dll导出foo()。在客户端代码中,bar()调用foo()baz()调用bar()。我需要确保barbaz在我的更改后都能正常工作。在我的情况下,调用堆栈实际上非常深,并且不容易手动跟踪,因为没有一个调用堆栈,我的库函数可以通过多种方式落在调用堆栈的顶部。

使用Visual Studio,或g ++或clang,有一种生成树的方法,使我的库函数位于根,并且分支是我的函数可以在调用顶部着陆的各种方式堆?我的意思是这个功能在一个流行的工具链中是否已经存在?如果没有,你知道生成这样一棵树的其他方法吗?

1 个答案:

答案 0 :(得分:1)

我认为任何编译器都没有选择来生成这些信息。

在一般情况下,有许多混淆因素会使这一点变得非常困难:

  • 如果代码中有递归,那么您想要的树实际上是具有周期的图形/网络。

  • 虚拟方法,函数指针和成员函数指针可能使这等同于暂停问题。如果您有两个具体的类AB共享一个提供虚方法foo()的公共基类,那么您必须进行详尽的分析以确定是否对{的特定调用{1}}通过指针或对基类的引用应被视为对foo()A::foo()或两者的调用。同样适用于各种口味的功能指针。

  • 如果您依赖可以回调代码的系统或其他第三方库,您最好拥有它们的来源。例如,Windows GUI程序通常具有从系统代码调用的窗口过程,可能是为了响应从代码到系统的调用。既然你不会拥有windows源代码,你必须假设任何时候都可以调用你的所有回调,因此你的“树”会有很多根。

解决这个问题的现代方法不是要分析你的库的所有调用方式,而是要记录它应该被调用的所有方式。构建一个测试套件,以您想要支持的所有合理方式调用库。然后你可以修补然后运行你的测试套件,看看你是否违反了图书馆的合同。如果在集成测试中,您发现库的客户端已被更改破坏,则表示测试套件不完整或客户端以不支持的方式调用库。