我已經參加了一些在線課程,介紹了堆棧的使用,他們很好,但理論上很好。因此,我一直試圖通過顯示一些簡單的C程序來理解它。我發現了幾種做法並嘗試使用gdb(backtrace ...)。如何在C中顯示堆棧的內容?
但是,我只能在發生錯誤時顯示堆棧信息。我想知道是否有辦法顯示堆棧,即使程序正確運行?
我已經參加了一些在線課程,介紹了堆棧的使用,他們很好,但理論上很好。因此,我一直試圖通過顯示一些簡單的C程序來理解它。我發現了幾種做法並嘗試使用gdb(backtrace ...)。如何在C中顯示堆棧的內容?
但是,我只能在發生錯誤時顯示堆棧信息。我想知道是否有辦法顯示堆棧,即使程序正確運行?
從理論上講,你不能確保有任何堆棧。
例如,一個編譯器可能會每次調用函數inline。或者它可以完成整個程序static analysis,並發現不需要堆棧。或者編譯器optimize有些調用爲tail calls。
更現實地說,一些函數內部的局部變量都可以進入寄存器(優化時)。
在實踐中,你可以在調試器中運行您的程序(如gdb
)和停止(在gdb
會議如與按CtrlÇ)的程序,然後運行的gdb
的backtrace
(或bt
)命令和調試過程的examine the stack。
(下面的信息是先進的;如果你是一個新手,不要混淆;且必須非常小心關於什麼是可行的,在編譯的時候,從你的程序中,或從你的調試器)
如果您要訪問的call stack編程在Linux上(與GNU libc的)一個程序中您可以使用backtrace functions(它們不是標準,並且可能無法正常工作,特別是具有較強的優化)。甚至Ian Taylor libbacktrace(然後更好地編譯所有代碼-g
,因爲libbacktrace
使用DWARF格式的調試信息)。
在評論,你又說:
我要尋找出在堆棧中的詳細信息的方式,例如參數,變量,SP等的價值。
這通常是不可能的(在運行時,從程序內部)。變量和參數只有編譯器已知(並且在運行時被遺忘)。在機器代碼中,您只有內存位置和寄存器(並且或許是堆棧幀,可能會因爲-fomit-stack-pointer
compile option而丟失....)。另外,你經常會用一些optimizations來編譯你的C代碼,然後很可能有些變量不在棧中(但只在寄存器中)。
注意C沒有introspection,或reflection,沒有明確continuations,而不是homoiconic語言。
這解決了我遇到的問題,並給出了一個非常好的解釋。非常感謝你 – Rick
我想知道是否有辦法顯示堆棧,即使程序正確運行?
是的:你可以在你程序執行的任意點檢查堆棧:只要在感興趣的指令上設置一個斷點,或者單步執行整個程序。
例如:
(gdb) break main
(gdb) run
... program stops after main prolog
(gdb) where # examine stack
(gdb) stepi # execute one instruction
(gdb) where
(gdb) stepi
... repeat until you reach syscall SYS_exit, or until you are too bored to continue
但是,使用調試器.... –
@BasileStarynkevitch他*問*如何使用調試器來檢查狀態(只是不在碰撞點)。注意問題上的GDB標籤。 –
我們正在談論'調用堆棧'而不是'數據堆棧',對吧? – Aubin
[C或C++中的打印調用堆棧]的可能重複(http://stackoverflow.com/questions/3899870/print-call-stack-in-c-or-c) – Aubin
是的確是Aubin,調用堆棧。感謝您的信息,我剛剛嘗試過。但回溯似乎只顯示被調用的功能。我正在尋找一種顯示堆棧中的詳細信息的方法,例如參數值,變量,SP等等。 – Rick