4

从 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

}

谁能解释为什么这会导致访问冲突读取位置这篇文章中描述了类似的症状。

4

2 回答 2

2

在加载您main的 .exe 之前,可执行文件将加载依赖库并执行它们自己的“ main”。它比这要复杂一些,但要理解的重要一点是代码首先在这些库中执行。如果那里有错误,它将崩溃。

您的错误消息提到这verifier.dll是问题的根源。您应该首先调查该 DLL。你自己建的吗?它是否具有运行所需的所有依赖项?

于 2017-03-09T05:50:33.017 回答
1

访问冲突是由在托管代码中使用静态变量引起的。我在 Windows 窗体 GUI 回调(托管代码)中使用了wstring类型的静态变量(本机 C++ 类型!)。我的猜测是程序试图在托管代码初始化结束之前初始化变量,甚至在到达程序入口点之前就导致了错误。

从托管代码中删除所有静态变量后,问题就消失了。

于 2017-03-13T03:14:33.377 回答