backtrace函數


 1、函數原型

#include <execinfo.h>    
int backtrace(void **buffer, int size);

  該函數獲取當前線程的調用堆棧,獲取的信息將會被存放在buffer中,它是一個指針數組,參數size用來指定buffer中可以保存多少個void*元素。函數的返回值是實際返回的void*元素個數。buffer中的void*元素實際是從堆棧中獲取的返回地址。

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

  該函數將backtrace函數獲取的信息轉化為一個字符串數組,參數bufferbacktrace獲取的堆棧指針,sizebacktrace返回值。函數返回值是一個指向字符串數組的指針,它包含char*元素個數為size。每個字符串包含了一個相對於buffer中對應元素的可打印信息,包括函數名、函數偏移地址和實際返回地址。

  backtrace_symbols生成的字符串占用的內存是malloc出來的,但是是一次性malloc出來的,釋放是只需要一次性釋放返回的二級指針即可。

void backtrace_symbols_fd(void *const *buffer, int size, int fd);

  該函數與backtrace_symbols函數功能相同,只是它不會malloc內存,而是將結果寫入文件描述符為fd的文件中,每個函數對應一行。該函數可重入。

2、函數使用注意事項

  • backtrace的實現依賴於棧指針(fp寄存器),在gcc編譯過程中任何非零的優化等級(-On參數)或加入了棧指針優化參數-fomit-frame-pointer后多將不能正確得到程序棧信息;
  • backtrace_symbols的實現需要符號名稱的支持,在gcc編譯過程中需要加入-rdynamic參數;
  • 內聯函數沒有棧幀,它在編譯過程中被展開在調用的位置;
  • 尾調用優化(Tail-call Optimization)將復用當前函數棧,而不再生成新的函數棧,這將導致棧信息不能正確被獲取。

3、捕獲異常信號並打印堆棧

  當程序出現崩潰等異常時,會接收到內核發送給進程的異常信號,進程接收到異常信號后,可以在處理信號的時候將程序的堆棧信息打印出來,以便於程序調試。

4、程序示例:

#include <stdio.h>
#include <execinfo.h>
#include <unistd.h>
#include <stdlib.h>
#define BACKTRACE_SIZE 100

void print_backtrace()
{
    void* buffer[BACKTRACE_SIZE]={0};
    int pointer_num = backtrace(buffer, BACKTRACE_SIZE);
    char** string_buffer = backtrace_symbols(buffer, pointer_num);
    if(string_buffer == NULL)
    {
        printf("backtrace_symbols error");
        exit(-1);
    }
    
    printf("print backtrace begin\n");
    for(int i = 0; i < pointer_num; i++)
    {
        printf("%s\n", string_buffer[i]);
    }
    printf("print backtrace end\n");

    free(string_buffer);
    
    return;
}

void func(int num)
{
    if(num > 0)
    {
        func(--num);
    }
    else
    {
        print_backtrace();
    }
}

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        printf("input param error");
        return -1;
    }
    
    int input_num = atoi(argv[1]);
    func(input_num);

    return 0;
}

執行結果如下,注意在編譯時帶-rdynamic參數

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM