从 Visual Studio 2012 升级到 Visual Studio 2015 后,我的项目在到达主函数之前就出现了堆损坏和访问冲突错误。根本没有我可以调试的代码。我检查了静态变量和任何可能在堆栈上创建的东西,但我似乎没有。我试图用空的 main 函数启动程序:
int main(){return 0;};
但我仍然收到访问冲突错误。该程序是一个带有混合 C++/CLI 代码的 GUI 形式。我确保我已经使用 VS2015 从源代码重建了第三方库(curl)并使用了正确的 DLL。不知道这些错误来自哪里 - 以前一切正常。我该如何修复/调试它?我搜索了很多,甚至尝试运行 gflags,但调试器不会停止任何人类可读的代码。错误内容如下:
MyProgramName.exe 中的 0x5A4C7988 (verifier.dll) 引发异常:0xC0000005:访问冲突读取位置 0xA46FEC13。
编辑 1: verifier.dll 与错误无关。事实证明,当我将图像文件添加到 gflags.exe 以尝试调试程序时,该库已加载。放弃这些更改后,我回到了原始错误消息,即 ntdll.dll 引发的堆损坏。
编辑 2: 我通过删除所有 .h 文件和 .cpp 文件将代码精简到最低限度,直到错误消失。这是一种非常低效的调试方式,但由于我不知道更好,我还是这样做了。
#include "MyGUI.h"
#include <boost/date_time/posix_time/posix_time.hpp>
[STAThread]
void main(array<String^>^ args) {
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Application::Run(gcnew MyProject::MyGUI);
}
如果我然后删除该行
#include <boost/date_time/posix_time/posix_time.hpp>
然后问题就消失了,gui开始时没有错误。
我得到访问冲突错误的原因是因为 posix_time 库默默地链接了一个 .lib 文件。当我从 VS2012 迁移到 VS2015 时,我已经重建了多个变体中的所有 boost 库,并且在项目中正确指定了其他库目录并包含了正确的库变体。我在其他项目中使用 posix_time 库没有问题,但是其他项目针对的是 x64 位,但我遇到的问题是 x32 位。我将 x32 位项目与我的 boost 构建的 lib32 目录链接,这是正确的。事实证明,我的应用程序崩溃的原因是 posix_time 库的 32 位版本中的一个错误。即使将我的 32 位应用程序链接到 x64 文件夹也可以解决问题。但是,由于我没有使用微秒,
BOOST_DATE_TIME_NO_LIB
编译器指令就足够了。根据boost 文档,
纳秒分辨率选项每个 ptime 使用 96 位底层存储,而微秒分辨率选项每个 ptime使用 64 位。
后一个引用和 x64 位库工作正常的事实让我认为该库的 32 位实现是错误的。
对于那些可能觉得它有帮助的人 - 这就是原因。至于我最初的问题,当堆损坏时,即使在到达入口点之前(因此没有任何源代码或调试信息可用) ,如何调试这样的崩溃,而不浪费 7 个小时来剥离项目,直到只有一行left - 我把这个问题留了下来。
如果有人可以指出找到此类错误的更好方法 - 这将非常有启发性。
编辑3: 显然这不是结束。在修复了 boost 库并恢复到完整代码后,我再次遇到了错误。问题是由在 GUI 窗体方法回调中使用静态变量引起的:
System::Void comboBoxStart_SelectionChangeCommitted(System::Object^ sender,
System::EventArgs^ e) {
static wstring LastChoice; //This line is enough to reproduce the crash
}
谁能解释为什么这会导致访问冲突读取位置?这篇文章中描述了类似的症状。