2017-02-18 66 views
2

我已經參加了一些在線課程,介紹了堆棧的使用,他們很好,但理論上很好。因此,我一直試圖通過顯示一些簡單的C程序來理解它。我發現了幾種做法並嘗試使用gdb(backtrace ...)。如何在C中顯示堆棧的內容?

但是,我只能在發生錯誤時顯示堆棧信息。我想知道是否有辦法顯示堆棧,即使程序正確運行?

+0

我們正在談論'調用堆棧'而不是'數據堆棧',對吧? – Aubin

+4

[C或C++中的打印調用堆棧]的可能重複(http://stackoverflow.com/questions/3899870/print-call-stack-in-c-or-c) – Aubin

+0

是的確是Aubin,調用堆棧。感謝您的信息,我剛剛嘗試過。但回溯似乎只顯示被調用的功能。我正在尋找一種顯示堆棧中的詳細信息的方法,例如參數值,變量,SP等等。 – Rick

回答

3

從理論上講,你不能確保有任何堆棧。

例如,一個編譯器可能會每次調用函數inline。或者它可以完成整個程序static analysis,並發現不需要堆棧。或者編譯器optimize有些調用爲tail calls

更現實地說,一些函數內部的局部變量都可以進入寄存器(優化時)。

在實踐中,你可以在調試器中運行您的程序(如gdb)和停止(在gdb會議如與按CtrlÇ)的程序,然後運行的gdbbacktrace(或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語言。

+0

這解決了我遇到的問題,並給出了一個非常好的解釋。非常感謝你 – Rick

2

我想知道是否有辦法顯示堆棧,即使程序正確運行?

是的:你可以在你程序執行的任意點檢查堆棧:只要在感興趣的指令上設置一個斷點,或者單步執行整個程序。

例如:

(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 
+0

但是,使用調試器.... –

+1

@BasileStarynkevitch他*問*如何使用調試器來檢查狀態(只是不在碰撞點)。注意問題上的GDB標籤。 –