在进入主

时间:2017-03-09 05:21:09

标签: c++ visual-studio-2015 heap-corruption mixed-code

从Visual Studio 2012升级到Visual Studio 2015后,我的项目在到达main函数之前就会出现堆损坏和访问冲突错误。根本没有我可以调试的代码。我检查了静态变量和可能在堆栈上创建的任何东西,但我似乎没有。我尝试使用空主函数启动程序:

int main(){return 0;};

但我仍然遇到访问冲突错误。该程序是一个带有混合C ++ / CLI代码的GUI表单。我确保我已经使用VS2015从源代码重建了第三方库(curl)并使用了正确的DLL。不知道这些错误来自哪里 - 一切都运转良好。我该如何修复/调试它?我google了很多,甚至尝试运行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目录相关联,这是正确的。事实证明,我的应用程序崩溃的原因是32位版posix_time库中的一个错误。即使将我的32位应用程序链接到x64文件夹也可以解决问题。但是,因为我没有使用微秒,

BOOST_DATE_TIME_NO_LIB

编译器指令就足够了。根据{{​​3}},

  

纳秒级分辨率选项每次使用96位底层存储,而微秒级分辨率每次使用64位

后一个引用以及x64位库工作正常的事实让我觉得该库的32位实现有问题。

对于那些可能会觉得有帮助的人 - 这就是原因。至于我的原始问题如何调试此类崩溃,甚至在达到入口点之前堆损坏(因此没有任何源代码或调试信息可用)而不浪费7小时到剥离项目,直到只剩下一行 - 我将问题打开。

如果有人能指出更好的方法来发现这种错误 - 这将是非常有益的。

编辑3: 显然这不是结束。修复boost库并恢复到完整代码后,我再次收到错误。问题是由GUI窗体表单方法回调中使用静态变量引起的:

System::Void comboBoxStart_SelectionChangeCommitted(System::Object^  sender,
                                                    System::EventArgs^  e) {

    static wstring LastChoice; //This line is enough to reproduce the crash

}

任何人都可以解释为什么这会导致访问冲突读取位置吗?类似的症状在boost documentation帖子中描述。

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

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

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