You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++中获取自定义异常抛出调用者的详细信息?

获取C++异常抛出的调用者信息

你现在遇到的问题是自定义异常无法追踪到具体抛出的函数,对吧?我来给你几个实用的方案:

方案1:在异常类中存储完整调用栈信息

你可以修改自定义的myexception类,让它在构造时就捕获当前的调用栈信息,这样在what()方法里就能返回包含调用链路的详细内容了。示例代码如下:

#include <exception>
#include <string>
#include <execinfo.h> // GCC环境下用于获取调用栈
#include <cstring>
#include <iostream>

class myexception : public std::exception {
private:
    std::string err_msg;
    void capture_stacktrace() {
        void* callstack[128];
        int frames = backtrace(callstack, 128);
        char** strs = backtrace_symbols(callstack, frames);
        if (strs) {
            for (int i = 0; i < frames; ++i) {
                err_msg += strs[i];
                err_msg += "\n";
            }
            free(strs);
        }
        err_msg += "My exception happened";
    }
public:
    myexception() {
        capture_stacktrace();
    }
    virtual const char* what() const noexcept override {
        return err_msg.c_str();
    }
};

void testException(){
    throw myexception(); // 注意:这里要抛出临时对象,而非全局对象,避免多次抛出共享实例
}
void doSomething2(){ testException(); }
void doSomething1(){ doSomething2(); }

int main () {
    try {
        doSomething1();
    } catch (std::exception& e) {
        std::cout << e.what() << '\n';
    }
    return 0;
}

注意:backtrace和backtrace_symbols是GCC的扩展API,Windows环境下需要替换为CaptureStackBackTrace这类系统API。另外你之前抛出全局对象myex的写法不推荐,多次抛出会共享同一个实例,容易导致信息混乱。

方案2:仅传递抛出异常的函数名

如果不需要完整调用栈,只想知道是哪个函数抛出的异常,可以在异常类里添加成员变量存储函数名,抛出时通过标准宏传入:

#include <exception>
#include <string>
#include <iostream>

class myexception : public std::exception {
private:
    std::string err_msg;
public:
    myexception(const std::string& func_name) {
        err_msg = "My exception happened in function: " + func_name;
    }
    virtual const char* what() const noexcept override {
        return err_msg.c_str();
    }
};

void testException(){
    throw myexception(__func__); // 使用C++11标准宏__func__获取当前函数名
}
void doSomething2(){ testException(); }
void doSomething1(){ doSomething2(); }

int main () {
    try {
        doSomething1();
    } catch (std::exception& e) {
        std::cout << e.what() << '\n';
    }
    return 0;
}

__func__是C++11纳入标准的宏,会返回当前函数的名称字符串,兼容性非常好。

方案3:调试阶段用工具直接追踪

如果你只是在调试时需要定位异常来源,完全可以借助编译器和调试工具的内置支持:

  • 编译代码时加上-g参数生成调试信息:g++ -g your_code.cpp -o your_program
  • 启动GDB调试:gdb ./your_program
  • 设置异常断点:catch throw
  • 运行程序:run
    当异常抛出时,GDB会自动暂停,输入bt命令就能看到完整的调用栈,直观又高效。

内容的提问来源于stack exchange,提问作者scoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:41:57