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

为什么C++捕获抛出的异常指针时,what()输出内容与预期不一致?

问题根本原因

你抛出的是栈上局部对象的指针,属于未定义行为,两种测试结果的差异只是未定义行为的不同表现而已。

第一个bad_exception测试现象解释

  • try块内定义的bad_exception e2是栈内存局部变量,作用域仅限于try块内部。
  • 执行throw &e2触发栈展开逻辑时,会先销毁try块内所有局部对象,e2的析构函数会被调用,其内部维护的what()返回的字符串资源已经被清理。
  • 你在catch块拿到的指针地址虽然和原地址一致,但指向的是已经被回收的无效内存,调用ex->what()属于野指针访问,因此输出Unknown exception。

第二个自定义类测试"正常"的原因

这只是未定义行为的巧合,完全不具备可复现性和可靠性:

  • 你自定义的A类是简单结构,默认析构函数没有任何清理内存的逻辑,对象销毁时不会主动覆盖内存内容。
  • 测试场景下栈展开后,原对象所在的栈内存还没有被其他操作覆盖,所以你碰巧能读到原来的字符串内容。
  • 只要调整编译优化等级、增加局部变量、更换运行环境,大概率会出现乱码、程序崩溃等异常结果。
正确的C++异常抛出实践

C++标准推荐直接抛出异常对象,用引用捕获,完全避免生命周期问题:

try {
    bad_exception e2 = bad_exception();
    cout << e2.what() << endl;
    cout << &e2 << endl;
    throw e2; // 抛出对象,异常机制会自动拷贝生成一个生命周期持续到catch结束的异常对象
}
catch (const bad_exception& ex) { // 用常量引用捕获,无额外拷贝,也不用担心生命周期
    cout << &ex << endl;
    cout << ex.what() << endl;
}

如果一定要抛出指针,必须抛出堆上动态分配的对象指针,且在catch块用完后手动释放,这种方式非常不推荐,极易造成内存泄漏:

try {
    bad_exception* e2 = new bad_exception();
    cout << e2->what() << endl;
    cout << e2 << endl;
    throw e2;
}
catch (bad_exception* ex) {
    cout << ex << endl;
    cout << ex->what() << endl;
    delete ex; // 必须手动释放,否则内存泄漏
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 08:18:00