簡體   English   中英

如何獲取調用 function 的名稱?

[英]How do I get the name of the calling function?

我正在使用 gnu 工具鏈。 如何在運行時找到 function 的調用者? 即例如 function B() 被許多使用 function 指針的函數調用。 現在,每當 B 被呼叫時,我都想打印呼叫者的姓名。 我需要這個來調試某個問題。

如果您使用的是 GNU,則可以使用回溯功能。 該手冊頁上有一個使用示例。

調用 function 的代碼位置__builtin_return_address()內部函數中的 gcc 保存。 要檢索它的名稱,您必須解析程序的符號表; 雖然可以通過dladdr()做到這一點,但這是有限制的:

  1. 在所有上下文中調用backtrace() / dladdr()可能並不安全(例如,從信號處理程序,或在多線程程序中並發,或從不能調用malloc()的上下文。)。
  2. 該操作不是即時的,但可能需要使調用線程進入睡眠狀態; 如果在調用時持有任何鎖,這是一件壞事。
  3. 退貨地址在名稱中的“可解析性”程度是有限的; 例如,如果有內聯函數調用您的 function,那么您的調用者的調用者就會出現( backtrace()手冊頁也說明了這一點,“BUGS”部分中的dladdr()也是如此)。
  4. 在 C++ 中,還有通過 con/destructors/initializers 調用的額外挑戰,其中 function 的“調用者”可能最終成為一些編譯器生成的元代碼,而您感興趣的實際位置可能在其他地方(調用者的調用者,甚至在調用堆棧中更深)。

這通常是解耦跟蹤和 function 名稱解析的更好方法; 即只是 output 返回地址(作為十六進制/二進制),然后根據程序運行時檢索到的符號表對生成的日志進行后處理。

Vasil Dimov在回答類似問題時指出的另一種方法是將 function 調用替換為報告或傳入調用 function 名稱的包裝宏。 這將適用於內聯函數,而回溯則不會。 另一方面,如果您通過引用調用 function 或以其他方式獲取其地址,則它將不起作用。

例如這個:

int B(int x){
    ...
}

可能變成:

int _B(int x, char *caller){
    printf("caller is %s\n", caller);
    ...
}

#define B(x) _B((x), __func__)

並且每次調用 B() 都會打印來電者姓名。 Vasil Dimov 以不同的方式構造它,直接在宏中打印名稱並保持 function 不變。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM