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

MSVC17调试器未处理异常行为异常问题咨询

MSVC17调试器异常行为问题分析

问题复现

第一段代码

#include <iostream>

int main()
{
    throw std::exception();
    std::cout << "Hello World!" << std::endl;
    return 0;
}
  • 未附加调试器:未处理异常正常终止程序
  • 附加调试器:触发异常后点击「Continue」,代码继续执行,仿佛异常从未发生(Linux GDB中测试会正常终止程序)

第二段代码

#include <iostream>

int main()
{
    try
    {
        throw std::exception();
    }
    catch (...)
    {
        throw;
    }
    std::cout << "Hello World!" << std::endl;
    return 0;
}
  • 附加调试器:触发异常后点击「Continue」,出现访问冲突:
    Exception thrown at 0x0000000000000000 in ConsoleApplication1.exe: 0xC0000005: Access violation executing location 0x0000000000000000.
    
    调试器陷入停滞

编译参数:

/JMC /permissive- /ifcOutput "ConsoleA.5d991025\x64\Debug\" /GS /W3 /Zc:wchar_t /ZI /Gm- /Od /sdl /Fd"ConsoleA.5d991025\x64\Debug\vc143.pdb" /Zc:inline /fp:precise /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /FC /Fa"ConsoleA.5d991025\x64\Debug\" /EHsc /nologo /Fo"ConsoleA.5d991025\x64\Debug\" /Fp"ConsoleA.5d991025\x64\Debug\ConsoleApplication1.pch" /diagnostics:column

问题解答

1. 为何调试器跳过未处理异常不终止程序?

这是MSVC调试器的**「仅我的代码(JMC)」**特性导致的。当启用JMC(编译参数包含/JMC)时,调试器会把标准库、系统代码标记为「非用户代码」。对于未处理的C++异常,调试器拦截后若判定异常来自非用户代码(或无用户代码的异常处理逻辑),点击「Continue」时会尝试跳过异常,让程序继续执行——这是为了方便开发者调试时忽略系统/库抛出的非关键异常,聚焦自身代码。

但实际上此时程序状态已被异常破坏,继续执行属于未定义行为,只是恰好能走到后续代码而已。

2. 为何第二段代码表现不同?

第二段代码中,异常被用户代码的catch(...)捕获后重新抛出,此时重新抛出的异常会被调试器判定为「用户代码发起的未处理异常」。点击「Continue」后,调试器找不到有效异常处理逻辑,程序进入Windows未处理异常流程,最终触发访问冲突——因为程序栈已处于异常展开的错误状态,没有合法后续执行路径,导致执行到空地址。

3. 能否关闭该「特性」?

可以,有两种方式:

  • 编译时关闭JMC:移除编译参数中的/JMC,重新编译程序。调试器会将所有代码视为待调试代码,未处理异常点击「Continue」后会按正常流程终止程序。
  • 调试器设置中关闭JMC:在Visual Studio的「调试」→「选项」→「调试」→「常规」中,取消勾选「启用仅我的代码」选项。无需重新编译,修改后调试行为即可改变。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 16:06:00