Visual Studio 2015中的afxwin.h问题Windows窗体应用程序

时间:2016-02-23 11:04:32

标签: winforms visual-studio-2015 c++-cli stdafx.h

不久之前我写了一个C ++ CLI Windows窗体应用程序,它在Visual Studio 2013中编译得很好。现在我想在Visual Studio 2015 Update 1中重新编译它,但是我遇到了问题,经过数小时的测试我发现罪魁祸首是afxwin.h

TL; DR - 有什么办法可以在使用Visual Studio编译的Windows窗体应用中使用stdafx.h(所以afxwin.h以及随附的所有其他导入) 2015年没有应用程序崩溃启动?

以下是如何重现我在我的应用中遇到的相同问题。

由于Windows Form不再可用作VS2015中的项目模板,我创建了一个名为测试 CLR空项目

Ctrl-Shift-A添加 UI > Windows窗体名为 MyForm

MyForm.cpp 中我添加了这个:

#include "MyForm.h"

using namespace System;
using namespace System::Windows::Forms;

[STAThread]
int main(cli::array<System::String^>^ args)
{
    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false);
    Test::MyForm form;
    Application::Run(%form);
}

配置属性&gt;下链接器&gt; 高级我将入口点设置为主要

配置属性&gt;下链接器&gt; 系统我将 SubSystem 设置为 Windows(/ SUBSYSTEM / WINDOWS)

COMPILE(DEBUG CONFIGURATION):编译时没有错误/警告

RUN:运行没有任何问题。

现在让我们尝试将 afxwin.h 添加到 MyForm.cpp

#include <afxwin.h>

配置属性&gt;下常规我将使用MFC 设置为在共享DLL中使用MFC

COMPILE(DEBUG CONFIGURATION):编译时没有错误/警告

RUN:该应用甚至无法启动,只是在表达式中显示调试断言失败错误 _CrtIsValidHeapPointer(block)

enter image description here enter image description here enter image description here 现在要解决此错误,我发现删除入口点是必要的,所以:

配置属性&gt;下链接器&gt; 高级我删除了入口点值(之前我设置为主要

COMPILE(DEBUG CONFIGURATION):编译时没有错误/警告

RUN:该应用再次无法启动,它不再显示 Debug Assertion Failed ,但未知模块中的System.AccessViolationException 和& #34;尝试读取或写入受保护的内存。这通常表明其他内存已损坏。&#34;

enter image description here enter image description here enter image description here enter image description here 这些是我在我的应用程序中遇到的错误,我想知道如何简单地包括afxwin.h在VS2015中提供所有这些问题,而在VS2013中没有。

我有什么办法可以修复它,而无需回到VS2013吗?

1 个答案:

答案 0 :(得分:1)

James McNellis为VS2015重写了C运行时库。他是一个很大的C ++粉丝,他编写的新代码患有慢性SIOF问题,这在C ++程序中很常见。静态初始化命令Fiasco肯定也存在于你的VS2013项目中,但事件并非发生在字节上,原始的CRT代码多年来暴露给SIOF,因此表现得更好。

在这种情况下,调试过于困难,失败的代码来自CRT源代码文件,该文件未包含在名为thread_safe_statics.cpp的安装中。不是100%肯定它的作用,因为没有源代码可以看,但文件的名称几乎没有想象。

MFC具有静态,需要在可用之前进行初始化。特别是,程序必须具有在恰当时间初始化的静态CWinApp变量。这要求入口点是WinMain(),在MFC中实现,并在源代码中明确声明CWinApp实例。像这样:

[STAThread]
int main(cli::array<System::String^>^ args)
{
    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false);
    Application::Run(gcnew Test::MyForm);
}

class MyMfcApp : public CWinApp {
public:
    virtual int Run() override {
        return main(__nullptr);
    }
} MyApp;

将链接器的EntryPoint设置重置为默认值(空白),以便首先初始化CRT,然后运行MFC的WinMain函数。并且要注意我选择了一条捷径,你没有args。我修复了main()函数中的一个错误,它错误地使用了堆栈语义

这个hack让你的程序再次运行。是否实际上正确是相当值得怀疑的。这会受到与大框架相关的“谁是老板”综合症的影响。不要依赖任何MFC窗口才能正常工作,因为它是调度消息的Winforms。但你也应该在VS2013中遇到这个问题。 “不要这样做”是唯一可靠的建议。