不久之前我写了一个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)
在配置属性&gt;下链接器&gt; 高级我删除了入口点值(之前我设置为主要)
COMPILE(DEBUG CONFIGURATION):编译时没有错误/警告
RUN:该应用再次无法启动,它不再显示 Debug Assertion Failed ,但未知模块中的System.AccessViolationException 和& #34;尝试读取或写入受保护的内存。这通常表明其他内存已损坏。&#34;
这些是我在我的应用程序中遇到的错误,我想知道如何简单地包括afxwin.h
在VS2015中提供所有这些问题,而在VS2013中没有。
我有什么办法可以修复它,而无需回到VS2013吗?
答案 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中遇到这个问题。 “不要这样做”是唯一可靠的建议。