C++ debug

C++ debug

在 C++ 中,查看程序的调用栈(Call Stack)通常用于调试崩溃、性能问题或逻辑错误等场景。以下是几种常用的方法来查看调用栈:

1. 使用 GDB 调试器查看调用栈

GDB(GNU Debugger)是 Linux 上非常流行的调试工具,可以用来查看 C++ 程序的调用栈。

示例:
假设有以下 C++ 程序:

#include <iostream>

void func_c() {
    throw std::runtime_error("An error occurred!");
}

void func_b() {
    func_c();
}

void func_a() {
    func_b();
}

int main() {
    try {
        func_a();
    } catch (const std::exception &e) {
        std::cerr << e.what() << std::endl;
    }
    return 0;
}

编译程序时加入调试信息(-g 选项):

g++ -g -o my_program my_program.cpp

运行 GDB 调试:

gdb ./my_program

在 GDB 中,运行程序:

(gdb) run

当程序崩溃或异常中断时,输入以下命令查看调用栈:

(gdb) backtrace  # 或简写为 bt

输出示例:

#0  func_c() at my_program.cpp:5
#1  func_b() at my_program.cpp:9
#2  func_a() at my_program.cpp:13
#3  main() at my_program.cpp:19

说明:

backtrace(或 bt)命令会显示从 main 函数到当前执行点的所有函数调用。
调用栈中的每一帧都包含函数名、文件名和行号。

2. 使用 libunwind 库

libunwind 是一个跨平台的库,支持更详细的调用栈分析。
示例:

#include <libunwind.h>
#include <iostream>

void print_stacktrace() {
    unw_cursor_t cursor;
    unw_context_t context;

    // 初始化上下文
    unw_getcontext(&context);
    unw_init_local(&cursor, &context);

    std::cout << "Call stack:\n";
    while (unw_step(&cursor) > 0) {
        char func_name[256];
        unw_word_t offset, pc;

        // 获取程序计数器 (PC)
        unw_get_reg(&cursor, UNW_REG_IP, &pc);
        if (pc == 0) break;

        // 获取函数名
        if (unw_get_proc_name(&cursor, func_name, sizeof(func_name), &offset) == 0) {
            std::cout << "0x" << std::hex << pc << ": " << func_name << " + 0x" << offset << "\n";
        } else {
            std::cout << "0x" << std::hex << pc << ": [unknown]\n";
        }
    }
}

void func_c() {
    print_stacktrace();
}

void func_b() {
    func_c();
}

void func_a() {
    func_b();
}

int main() {
    func_a();
    return 0;
}

编译并运行:

g++ -g -lunwind -o my_program my_program.cpp

./my_program

输出示例:

Call stack:
0x4008a3: print_stacktrace + 0x3f
0x4008c3: func_c + 0x7
0x4008d3: func_b + 0x7
0x4008e3: func_a + 0x7
0x4008f3: main + 0x7
0x7f8c3f2ee0b3: __libc_start_main + 0xf3
0x4007ee: _start + 0x2e

3. 借助 IDE 调试器

现代 IDE (如 CLion、Visual Studio、VSCode)通常集成了强大的调试器,允许你在调试模式下查看调用栈。

使用方式:
在程序中设置断点。
启动调试器。
当程序暂停时,查看调用栈窗口(通常在调试面板中)。

总结

  • GDB :适合在命令行下调试崩溃或运行时问题,使用 backtrace 查看调用栈。
  • libunwind :功能强大,支持跨平台的调用栈分析。
  • IDE 调试器 :提供图形化界面,适合实时调试。
posted @ 2024-12-12 19:15  michaelchengjl  阅读(9)  评论(0编辑  收藏  举报