How to get a stack trace for C++ using gcc with line number information?

后端 未结 14 2012
长发绾君心
长发绾君心 2020-11-27 09:54

We use stack traces in proprietary assert like macro to catch developer mistakes - when error is caught, stack trace is printed.

I find gcc\'s pair

14条回答
  •  挽巷
    挽巷 (楼主)
    2020-11-27 10:31

    here is my solution:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include "regex"
    
    std::string getexepath() {
        char result[PATH_MAX];
        ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
        return std::string(result, (count > 0) ? count : 0);
    }
    
    std::string sh(std::string cmd) {
        std::array buffer;
        std::string result;
        std::shared_ptr pipe(popen(cmd.c_str(), "r"), pclose);
        if (!pipe) throw std::runtime_error("popen() failed!");
        while (!feof(pipe.get())) {
            if (fgets(buffer.data(), 128, pipe.get()) != nullptr) {
                result += buffer.data();
            }
        }
        return result;
    }
    
    
    void print_backtrace(void) {
        void *bt[1024];
        int bt_size;
        char **bt_syms;
        int i;
    
        bt_size = backtrace(bt, 1024);
        bt_syms = backtrace_symbols(bt, bt_size);
        std::regex re("\\[(.+)\\]");
        auto exec_path = getexepath();
        for (i = 1; i < bt_size; i++) {
            std::string sym = bt_syms[i];
            std::smatch ms;
            if (std::regex_search(sym, ms, re)) {
                std::string addr = ms[1];
                std::string cmd = "addr2line -e " + exec_path + " -f -C " + addr;
                auto r = sh(cmd);
                std::regex re2("\\n$");
                auto r2 = std::regex_replace(r, re2, "");
                std::cout << r2 << std::endl;
            }
        }
        free(bt_syms);
    }
    
    void test_m() {
        print_backtrace();
    }
    
    int main() {
        test_m();
        return 0;
    }
    

    output:

    /home/roroco/Dropbox/c/ro-c/cmake-build-debug/ex/test_backtrace_with_line_number
    test_m()
    /home/roroco/Dropbox/c/ro-c/ex/test_backtrace_with_line_number.cpp:57
    main
    /home/roroco/Dropbox/c/ro-c/ex/test_backtrace_with_line_number.cpp:61
    ??
    ??:0
    

    "??" and "??:0" since this trace is in libc, not in my source

提交回复
热议问题