2009-09-02 36 views
2

我有一个使用第三方库的C++应用程序。我的代码中的每个地方都有对该库的调用。我想跟踪所有这些电话。如何将所有调用跟踪到C++中预定义的函数?

这很容易,如果这些是我的代码中的函数 - 我会插入一个宏,它将获得当前函数的名称和调用启动时间,并将其传递给本地对象构造函数,然后在函数退出时,该对象将销毁并追踪必要的数据。该宏将扩展为配置的空字符串,我不需要跟踪来消除相关开销。

有没有一些简单的方法可靠地做一些类似的调用外部库?我拥有的库的所有接口都是带有函数原型的.h文件,它包含在我的代码中。

回答

0

那么你可以在第三方lib调用的顶部添加另一个图层。这样你可以添加任何复杂的追踪包装你想要的。

例如

struct trace 
{ 
    static void myfoo() { cout << "calling foo" << endl; foo(); } 
    // or 
    // static void myfoo() { if (_trace) {..} foo(); } 
}; 
4

你可以试着写暴露相同的接口和内部重定向到原来的lib中调用一个包装库。

然后,您可以轻松地将您的跟踪代码添加到包装函数。 您项目的所有变化都是您要链接的库。

要防止定义多个符号,可以将外部库头包含在单独的名称空间中。

编辑:

包含在一个命名空间中的外部库头不解决该符号的问题。您必须在头中使用一个宏,以重命名原始函数和代码中的每一处。使用这样的新包装库头:

#define originalExportedFunction WRAPPED_originalExportedFunction 

extern "C" int originalExportedFunction(int); 

你在包装lib中实现,那么可能是:

extern "C" int WRAPPED_originalExportedFunction(int i) 
{ 
    //trace code here... 
    return originalExportedFunction(i); 
} 
+1

如果您将标头包含在命名空间中,则标头中定义的符号将与库中定义的符号位于不同的命名空间中。 – 2009-09-02 14:30:30

+0

@Jon:你说得对,使用命名空间并不能解决符号问题。 但作为替代方案,您始终可以使用重新命名被调用函数的宏函数,并让您的库导出重命名的函数名称。然后重命名的函数将调用原始函数,并且没有符号冲突。 – 2009-09-02 21:52:25

3

如果你碰巧Unix/Linux下使用工作

ltrace

跟踪库调用,

strace的

系统调用。尽管如此,这些命令在代码解决方案中没有。您还可以使用-callgrind选项查看valgrind以进行配置。

0

由于您似乎知道要调用的函数(以及这些调用的签名),因此仍然可以使用宏/类包装器的想法。例如:

typedef void (*pfun)(int); 

class Foo { 
    pfun call; 
    public: 
     Foo(pfun p) : call(p) {} 
     void operator()(int x) { 
      std::cout << "Start trace..." << std::endl; 
      (*call)(x); 
      std::cout << "End trace" << std::endl; 
     } 
}; 

void bar (int x) { 
    std::cout << "In bar: " << x << std::endl; 
} 

int main() { 

    Foo foo(&bar); 
    foo (42); 
    return 0; 

} 
0

尝试为所有接口apis创建一个宏,例如, 假设API被称为:

obj->run_first(var1); 

然后创建下面的宏:

#define obj->run_first(args) \ 
    dumptimestamp(__FUNCTION__, __LINE__); \ 
    obj->run_first(args);     \ 
    dumptimestamp(__FUNCTION__, __LINE__); 

您可以从一个lib的头文件生成类似于宏的列表中,因为它具有的所有的接口方法列表。

dumptimestamp将转储时间戳以及函数和行号。

0

如果你不想改变你的代码,那么有办法通过仪器来做这样的事情。如果你有兴趣以这种方式,来看看被称为一个很好的动态二进制仪表工具包PIN(由英特尔维护):

http://www.pintool.org/downloads.html

随着PIN,您可以在功能插入自己的代码进入/退出。一个例子是捕获的malloc /免费:

http://www.pintool.org/docs/29972/Pin/html/index.html#FindSymbol

这是完全不同的方式来跟踪函数调用。但是,值得一看。

相关问题