1. 程式人生 > >linux使用者程式呼叫棧列印backtrace

linux使用者程式呼叫棧列印backtrace

在除錯程式的時候,有時候程式跑到一個分支不知道怎麼呼叫到的/在走到不應該走的分支後希望把整個呼叫棧打印出現,在linux使用者程式裡面有一個glibc庫函式backtrace可以打印出當前程序棧資訊(如果希望程序退出的話可以用ASSERT(),在核心態中有對應的dump_stack()和BUG()/BUG_ON()):

int backtrace(void **buffer, int size);

該函式用於獲取當前現場的呼叫堆疊。函式返回值是指標陣列中指標的個數,buffer是用來存放指標的指標陣列,size是陣列的最大個數。

buffer中的指標實際上是從堆疊獲取的函式的返回地址。

char **backtrace_symbols(void *const*buffer, int size);

backtrace_symbols將從backtrace函式獲取的資訊轉化為一個字串陣列. 引數buffer應該是從backtrace函式獲取的指標陣列,size是該陣列中的元素個數(backtrace的返回值)

函式返回值是一個指向字串陣列的指標,它的大小同buffer相同.每個字串包含了一個相對於buffer中對應元素的可列印資訊.它包括函式名,函式的偏移地址,和實際的返回地址。

現在,只有使用ELF二進位制格式的程式才能獲取函式名稱和偏移地址.在其他系統,只有16進位制的返回地址能被獲取.另外,你可能需要傳遞相應的符號給連結器,以能支援函式名功能(比如,在使用GNU ld連結器的系統中,你需要傳遞(-rdynamic), -rdynamic可用來通知連結器將所有符號新增到動態符號表中,如果你的連結器支援-rdynamic的話,建議將其加上!)
該函式的返回值是通過malloc函式申請的空間,因此呼叫者必須使用free函式來釋放指標.
注意:如果不能為字串獲取足夠的空間函式的返回值將會為NULL;

backtrace還可以用來定位段錯誤。例如如果程式發生段錯誤系統都會發送SIGSEGV訊號給程式,預設處理是程式退出,可以在收到該訊號的處理函式中增加通過backtrace把棧資訊打印出來。

如下是一個列印的棧資訊,包括函式名和對應的偏移地址

Obtained6stackframes.nm
./backstrace_debug(dump+0x45)[0x80487c9]
[0x468400]
./backstrace_debug(func_b+0x8)[0x804888c]
./backstrace_debug(func_a+0x8)[0x8048896]
./backstrace_debug(main+0x33)[0x80488cb]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x129113]

接著可以用objdum反彙編出二進位制檔案,找到對應的位置。
objdump -d test > test.s
在test.s中搜索func_b然後加上偏移大概找到對應的出錯語句。

我們也可以通過addr2line來檢視
addr2line 0x804888c -e backstrace_debug -f 
輸出:
func_b
/home/astrol/c/backstrace_debug.c:57

相關推薦

linux使用者程式呼叫列印backtrace

在除錯程式的時候,有時候程式跑到一個分支不知道怎麼呼叫到的/在走到不應該走的分支後希望把整個呼叫棧打印出現,在linux使用者程式裡面有一個glibc庫函式backtrace可以打印出當前程序棧資訊(如果希望程序退出的話可以用ASSERT(),在核心態中有對應的dump_s

Linux 多執行緒程式呼叫malloc,backtrace引發死鎖問題的除錯

       最近,參與公司開發一專案,為提高Server端的執行效率,將Server程式設計為多執行緒結構。在一次測試中發現了Server無任何響應的問題,我的第一判斷是Server程式出現了死鎖。於是,使用pstack命令檢視各執行緒的堆疊狀態。 # pstack  程

通過/proc檢視Linux核心態呼叫來定位卡死問題

[[email protected] ~]# cat /proc/27288/sched find (27288, #threads: 1) --------------------------------------------------------- se.exec_start

linux下函式呼叫Backtraces函式

Backtraces A backtrace is a list of the function calls that are currently active in a thread. The usual way to inspect a backtrace of a

C++中backtrace列印函式呼叫callstack-dbg_assert

1. 使用backtrace()函式獲取呼叫棧,是一個指標陣列,返回獲取到的呼叫棧個數,結果放到傳入的指標數組裡面; 2. 呼叫backtrace_symbols()把獲取的指標陣列和陣列中呼叫棧個數傳遞給該函式,會返回一個新的指標陣列,    裡面是已經轉換成符號表的呼叫棧資訊

Linux下如何在程式中獲得當前呼叫資訊

主要使用backtrace和backtrace_symbols兩個函式。 #include#includeusing namespace std; //返回當前堆疊呼叫列表 string print_trace(int fd, int filter_first_lines

不同程式語言在發生stackoverflow之前支援的呼叫最大巢狀層數

今天我的一位同事在微信群裡發了一張圖片,勾起了我的好奇心:不同程式語言支援的函式遞迴呼叫的最大巢狀層數是? Java 1.8 private static void recur(int i){ System.out.println("Stack level: " +

java層列印呼叫兩中方法

RuntimeException here = new RuntimeException("here"); here.fillInStackTrace(); Log.d("my_log", "Cal

Linux驅動程式編寫&&應用程式對她的呼叫

        Linux驅動程式的開發,我相信這是很多致力於嵌入式學習的騷年的終極夢想,不管是技術含量,還是薪金待遇,她都一一完美的體現了出來!當然,crk_13也一樣!不過,越是誘人的東西往往也越是可望而不可即,或許大家都對驅動開發的難度之大,要求之高有所耳聞!以我個人

Linux】shell呼叫Java程式main方法通過crontab定時執行

最近一個專案需要寫一個batch定時讀取檔案往資料庫裡插入記錄,第一次寫,遇到好多問題,記錄一下。 先從shell如何呼叫java說起 建立如下目錄結構 batch                          根目錄 ├── bin                

Android下列印呼叫

1. Java層如何列印呼叫棧? 在優化Android啟動過程時,同事給出一種打印出呼叫棧的函式。分享一下     java.util.Map<Thread, StackTraceElement[]> ts = Thread.getAllStack

程式的記憶體佈局——函式呼叫的那點事

[注]此文是《程式設計師的自我修養》的讀書總結,其中摻雜著一些個人的理解,若有不對,歡迎拍磚。 程式的記憶體佈局 現代的應用程式都執行在一個虛擬記憶體空間裡,在32位的系統裡,這個記憶體空間擁有4GB的定址能力。現代的應用程式可以直接使用32位的地址進行定址,整個記憶

android列印呼叫的方法

文章1: 列印呼叫棧是android平臺問題定位的基本方法,如果需要知道誰在呼叫某個函式,可以在此函式中新增列印呼叫棧函式,弄清楚函式之間的呼叫關係。 1. Java層列印呼叫棧方法RuntimeException here = new RuntimeExceptio

C++中如何列印呼叫

if (your_condition_bool_val == true) { void * array[10]; char ** strings; size_t size = backtrace(array, 10); strings

C++ 程式崩潰呼叫堆疊列印

程式現場釋出,最頭痛程式崩潰 但是日誌又找不出什麼蛛絲馬跡  win32下可以增加如下 可以在release下列印呼叫堆疊資訊   //.h #ifndef _CALL_STACK_TOOL_2017_10_30_ #define _CALL_STACK_TOOL_201

java 列印函式呼叫

 有時候需要跟一些程式碼的呼叫流程,這時候列印函式的呼叫棧就非常好用。 java.util.Map<Thread, StackTraceElement[]> ts

linux的C程式 呼叫 shell指令碼,獲取shell的執行結果

linux下通過C執行命令的時候一半都是使用system()方法,但是該方法執行命令返回的值是-1或0,而有時候我們需要得到執行命令後的結果。可以使用管道實現 輸出到檔案流的函式是popen(),例如 FILE *isr; isr = popen("ls -l","r"

Android C++層列印呼叫

在Android framework的C++層或其他C++服務中需要列印呼叫棧時,可以使用android中的CallStack類進行列印,該類的實現如下: /* * Copyright (C) 2007 The Android Open Source Project *

程式頁面應用

頁面棧原理 小程式的每個頁面都是一個page物件,拿到page物件就可以操作他的方法以及屬性,page是放到頁面棧裡面的並且最多有5個 頁面棧應用 通過getCurrentPages();獲取頁面棧內所有的Page物件,去某一個Page物件即可操作其方法和屬性。 比如頁面跳轉傳

Linux程式——進度條

在linux下的緩衝有三種方式:無緩衝,行緩衝和全緩衝,當然在C程式中緩衝區的方式是以行緩衝的方式重新整理的,也就是說程式要在輸入流中獲取一個行結束標誌(換行或者是EOF)才會顯示在輸出螢幕上。 舉個栗子: 執行結果為先在螢幕上列印hello再sleep3秒: 另一個栗子: