我正在尋找一種聰明的方式來跟蹤函數調用和返回。 我知道我可以使用調試器,但我希望有一種方法可以在調用函數時將它們打印到終端上,而不必遍歷代碼。
我在想我可以使用預處理器,但我不確定最好的方法是什麼。
或者有沒有辦法使用gdb打印出有用的信息,而無需單步執行代碼。C/C++需要一個聰明的方式來跟蹤函數調用
回答
或者是有使用gdb輸出,這將是非常有用的信息,而不必單步執行代碼
是一種方式。僅在您實際關心的功能中設置斷點。使用「繼續」,直到你到達這些功能或直到你的程序崩潰。然後使用「backtrace」(或「bt」)來獲取堆棧跟蹤。
#define BEGIN_FUNC(X) printf("Function %s Entered",X)
#define END_FUNC(X) printf("Function %s End",X)
foo()
{
BEGIN_FUNC(__func__);
//Your code here
END_FUNC(__func__);
}
我認爲,如果你寫一個宏象上面和描述,然後你可以在終端上的日誌,用它爲每個函數。
+1我的答案缺乏 – PostMan 2010-07-23 04:01:04
這基本上是如何侵入性分析。 – 2010-07-23 04:27:23
這是我做了很多次... 一個很好的技術... – Microkernel 2010-07-23 05:21:32
有一個__FUNCTION__
(Reference)宏用於確定您所在的方法(格式爲Class::Method
),但這更多的是手動過程。
但是,當我最近需要相同的「跟蹤」信息時,我找不到自動方法。
你可能想看看Valgrind's Callgrind它可以跟蹤函數調用到一個漂亮的圖形。它將顯示函數調用,但不顯示參數或返回值。
大多數編譯器允許您在函數調用之前和之後插入檢測函數。
在MSVC他們_penter和_pexit
好文章 http://www.drdobbs.com/184403601
在GCC你可以使用-finstrument函數
http://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Code-Gen-Options.html
您可以使用調試libaries或映射文件,以獲得更多信息。
你不會發生TP知道如何查找符號表中的功能在gcc – 2010-07-23 04:16:03
你想找到名稱或查找的東西像調試對象中的參數等? – 2010-07-23 22:08:18
只要名字就沒問題。 #delay – reader 2015-02-24 03:27:09
如果您需要使其自動化,您可以查看TARGET_ASM_FUNCTION_END_PROLOGUE
和TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
。這些是編譯器鉤子,它可以讓你指定要與正常的函數序言/結尾一起發送的程序集 - 在你的情況下,你會用它們發出一個小程序集來記錄有問題的函數的入口/出口。您還可以查看FUNCTION_PROFILE
和/或PROFILE_HOOK
(例如:http://gcc.gnu.org/onlinedocs/gccint/Function-Entry.html)。
一個非常有趣的解決方案是使用RAII來控制函數的範圍。這將有性能有很大影響,但會在日誌中相當明確的,而不需要用戶在所有可能的代碼路徑添加儀器可能會留下功能:
class ScopeLogger {
public:
ScopeLogger(std::string const & msg) : msg(msg)
{ std::cout << "Enter: " << msg << std::endl; }
~ScopeLogger()
{ std::cout << "Exit: " << msg << std::endl; }
std::string msg;
};
#if DEBUG
#define FUNCTION(x) ScopeLogger l_##x##_scope(x);
#endif
void foo(int value) {
FUNCTION(__FUNCTION__);
if (value > 10) throw std::exception;
std::cout << "." << std::endl;
}
int main() {
foo(0); // Enter: foo\n.\nExit: foo
foo(100); // Enter: foo\nExit: foo
}
如果代碼是單線程的,你甚至可能希望與部分縮進級別添加一個靜態變量來ScopedLogger
不會增加太多本來已經很沉重的性能影響:
class ScopeLogger {
public:
ScopeLogger(std::string const & msg) : msg(msg)
{ std::cout << std::string(indent++,' ') << "Enter: " << msg << std::endl; }
~ScopeLogger()
{ std::cout << std::string(--indent,' ') << "Exit: " << msg << std::endl; }
std::string msg;
static int indent;
};
int ScopeLogger::indent = 0;
相當侵擾性,但不及Praveen's。 – Stephen 2010-07-23 12:50:51
你的代碼是否被編譯? 'std :: string'的構造器在哪裏可以使這個'std :: string(indent ++,「」)'有效? – 2012-04-25 15:23:35
@ bruce.banner:很好的結果,當你在網頁中輸入而不是在編輯器中編譯時,會發生這種情況。第二個參數*必須是*'char',而不是'char *'(即,我錯誤地用雙引號引用了單引號)。無論如何,這只是一個想法,代碼還有其他問題,包括但不限於線程安全性(或缺少它)。 – 2012-04-25 15:27:24
由於您使用GCC,你也可以使用連接器的功能包裝。
Link-Time Replacement/Wrapping
– GCC option: -Wl,--wrap,function_name
基本上,你可以採取所謂的「函數名()」函數和一個名爲「__wrap_function_name()」函數包裹。您可以通過調用「__real_function_name()」來訪問原始函數。
前段時間我聽了一個關於面向方面編程的演講,其中包括你想要實現的內容。也許搜索這個詞有幫助。
- 1. FOR XML EXPLICIT - 需要一種聰明的方式來查詢XML
- 2. 這有一個更聰明的方式來使用php next/previous_post?
- 3. 需要這個聰明的幫助
- 4. 聰明的方式來預測寬度
- 5. DLL跟蹤函數調用
- 6. 聰明的方法來CSS3
- 7. 我要尋找一個聰明的辦法來檢查傳遞給函數
- 8. 需要跟蹤API的方法
- 9. 我需要跟蹤哪些進程API來跟蹤服務?
- 10. 有一個JavaScript函數私人跟蹤它的調用次數
- 11. 不錯的方式來跟蹤ST monad函數之間的幾個引用?
- 12. 我需要從javascript調用它後聲明一個PHP函數
- 13. 一個真正聰明的軌道幫手需要
- 14. 跟蹤所有的Excel函數調用
- 15. 聰明的方式來創建一個窗體來生成基於XSD的XML
- 16. C-需要調用一個函數
- 17. 兩個函數調用,但只有一個跟蹤顯示
- 18. PHP函數只調用一個參數,我需要它來調用一大堆
- 19. java反射來調用一個需要Comparable []參數的方法
- 20. Plone的4個聰明通用安裝更新需要
- 21. C++:跟蹤時間函數調用
- 22. 如何跟蹤T-SQL函數調用
- 23. 逆足跟蹤調用函數
- 24. 如何使用'armcc'編譯器來跟蹤函數調用?
- 25. 函數drupal的跟蹤跟蹤
- 26. 跟蹤Perl方法調用
- 27. Android方法調用跟蹤
- 28. 需要跟蹤,利用GPS的Android
- 29. 清潔/更聰明的方式來使用循環
- 30. 聰明的方法來檢查超級
感謝回溯,它運作良好。 – 2010-07-23 04:08:05