2009-09-02 21 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

這是完全不同的方式來跟蹤函數調用。但是,值得一看。

相關問題