天天看點

【程式中列印調用棧資訊方法】 backtrace和backtrace_symbols函數

在頭檔案"execinfo.h"中聲明了三個函數用于擷取目前線程的函數調用堆棧

Function: int backtrace(void **buffer,int size)

該函數用與擷取目前線程的調用堆棧,擷取的資訊将會被存放在buffer中,它是一個指針清單。參數 size 用來指定buffer中可以儲存多少個void* 元素。函數傳回值是實際擷取的指針個數,最大不超過size大小

在buffer中的指針實際是從堆棧中擷取的傳回位址,每一個堆棧架構有一個傳回位址

注意某些編譯器的優化選項對擷取正确的調用堆棧有幹擾,另外内聯函數沒有堆棧架構;删除架構指針也會使無法正确解析堆棧内容

Function: char ** backtrace_symbols (void *const *buffer, int size)

backtrace_symbols将從backtrace函數擷取的資訊轉化為一個字元串數組. 參數buffer應該是從backtrace函數擷取的數組指針,size是該數組中的元素個數(backtrace的傳回值)   

函數傳回值是一個指向字元串數組的指針,它的大小同buffer相同.每個字元串包含了一個相對于buffer中對應元素的可列印資訊.它包括函數名,函數的偏移位址,和實際的傳回位址

現在,隻有使用ELF二進制格式的程式和苦衷才能擷取函數名稱和偏移位址.在其他系統,隻有16進制的傳回位址能被擷取.另外,你可能需要傳遞相應的标志給連結器,以能支援函數名功能(比如,在使用GNU ld的系統中,你需要傳遞(-rdynamic))

該函數的傳回值是通過malloc函數申請的空間,是以調用這必須使用free函數來釋放指針.

注意:如果不能為字元串擷取足夠的空間函數的傳回值将會為NULL

Function:void backtrace_symbols_fd (void *const *buffer, int size, int fd)

backtrace_symbols_fd與backtrace_symbols 函數具有相同的功能,不同的是它不會給調用者傳回字元串數組,而是将結果寫入檔案描述符為fd的檔案中,每個函數對應一行.它不需要調用malloc函數,是以适用于有可能調用該函數會失敗的情況

總結:

1、backtrace可以在程式運作的任何地方被調用,傳回各個調用函數的傳回位址,可以限制最大調用棧傳回層數;

2、在backtrace拿到函數傳回位址之後,backtrace_symbols可以将其轉換為編譯符号,這些符号是編譯期間就确定的;