解决方案:

在VS2015中:

  1. 项目属性 → C/C++ → 代码生成 → 基本运行时检查

    • 尝试设置为"默认"

  2. 项目属性 → C/C++ → 常规 → 调试信息格式

    • 确保设置为"程序数据库(/Zi)"

  3. 项目属性 → C/C++ → 优化

    • 调试版本设置为"禁用(/Od)"=

在设置第一项时,问题已解决,咨询GPT,GPT给出的解释是:代码本身并没有真正破坏栈,而是 VS2015 的运行时调试检查机制 (_RTC) 在退出阶段误报/触发了栈损坏检测。

Visual Studio 的编译器(特别是 VS2013 / VS2015)有一组叫做 Runtime Checks(运行时检查) 的编译选项:

选项编译参数作用
默认(无 _RTC)不生成额外的检查代码
Stack Frames (/RTCs)_RTCsu在函数入口/出口检查栈完整性
Uninitialized Variables (/RTCu)_RTC1检查局部变量未初始化使用
Both (/RTC1)_RTC1同时启用两者

当启用了 /RTC1(VS 的“基本运行时检查 → 启用所有检查”),
编译器会在每个函数的入口和出口插入一些额外代码来验证:

“当前函数的栈帧有没有被别的地方写坏”。

代码在逻辑上没错(线程退出、句柄关闭都正确),
但是因为 _RTC 检查栈时机早于某些 静态对象析构 / CRT 清理逻辑
在多线程 + 静态对象场景下,栈边界值可能被中间的 CRT/线程库访问或修改,
于是 _RTC 认为栈损坏,从而报出:

Run-Time Check Failure #2 - Stack around the variable 'myTimer' was corrupted.

不是变量真的被写坏,而是_RTC 的监视哨(guard bytes)在多线程场景下被别的 runtime 写入了。

VS2015 的 CRT (MSVCRT140) 在多线程清理 std::thread、静态局部对象时,
会在 _RTC 还在监视的栈空间上调用析构;

_RTC 的检测逻辑没有意识到线程局部析构发生时栈帧已经迁移;

所以很多 perfectly valid 的多线程代码在 VS2015 + /RTC1 下都会报错。在 VS2017 之后,这种误报明显减少。

这类程序(使用线程、同步、Windows API)建议配置如下:

模式推荐设置原因
Debug✅ “默认”(关闭 /RTC)避免误报,调试体验更稳定
Release✅ “默认”生产环境下本来就不应该启用运行时检查
单线程算法测试可以临时启用 /RTC1帮助检测越界或未初始化
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐