afxwin.h 问题 Visual Studio 2015 Windows 表单应用程序
afxwin.h issues in Visual Studio 2015 Windows Form App
不久前我写了一个 C++ CLI Windows Form 应用程序,它在 Visual Studio 2013 中编译得很好。现在我想在 Visual Studio 2015 Update 1 中重新编译它,但是我'我遇到了一个问题,经过几个小时的测试,我发现罪魁祸首是 afxwin.h
.
TL;DR - 有什么方法可以在 Windows 使用 Visual Studio 2015 编译的表单应用程序没有在启动时崩溃?
以下是重现我在我的应用中遇到的相同问题的方法。
由于 Windows Form 在 VS2015 中不再可用作项目模板,我创建了一个名为 Test 的 CLR 空项目
Ctrl-Shift-A 添加一个 UI > Windows 表单 调用 我的表格
在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);
}
在配置属性 > 链接器 > 高级下我设置了条目指向到main
在配置属性 > 链接器 > 系统下我设置了子系统 至 Windows (/SUBSYSTEM/WINDOWS)
编译(调试配置): 编译没有 errors/warnings
运行: 运行没有任何问题。
现在让我们尝试将 afxwin.h 添加到 MyForm.cpp:
#include <afxwin.h>
在配置属性>常规下,我将MFC的使用设置为在共享 DLL 中使用 MFC
编译(调试配置): 编译没有 errors/warnings
运行: 应用甚至无法启动,它只是显示 调试断言失败 表达式错误 _CrtIsValidHeapPointer(块)
现在要修复此错误,我发现有必要删除 入口点 ,因此:
在配置属性 > 链接器 > 高级下我删除了条目Point值(我之前设置为main)
编译(调试配置): 编译没有 errors/warnings
运行: 应用程序甚至无法启动,它不再显示 Debug Assertion Failed 但 System.AccessViolationException 在未知模块中 和 "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
这些是我在我的应用程序中遇到的错误,我想知道简单地包含 afxwin.h
怎么可能在 VS2015 中给出所有这些问题,而在 VS2013 中却没有。
有什么办法可以修复它,而无需返回到 VS2013?
James McNellis 为 VS2015 重写了 C 运行时库。他是 C++ 的忠实粉丝,他编写的新代码存在 C++ 程序中常见的慢性 SIOF 问题。 Static Initialization Order 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 让您的程序再次 运行。它是否实际上正确是相当值得怀疑的。这患有与大型框架相关的 "Who is the Boss" 综合症。不要依赖任何 MFC window 才能正常工作,因为它是 Winforms 正在调度消息。但是你应该在 VS2013 中也遇到过这个问题。 "Don't do it" 是唯一可靠的建议。
不久前我写了一个 C++ CLI Windows Form 应用程序,它在 Visual Studio 2013 中编译得很好。现在我想在 Visual Studio 2015 Update 1 中重新编译它,但是我'我遇到了一个问题,经过几个小时的测试,我发现罪魁祸首是 afxwin.h
.
TL;DR - 有什么方法可以在 Windows 使用 Visual Studio 2015 编译的表单应用程序没有在启动时崩溃?
以下是重现我在我的应用中遇到的相同问题的方法。
由于 Windows Form 在 VS2015 中不再可用作项目模板,我创建了一个名为 Test 的 CLR 空项目
Ctrl-Shift-A 添加一个 UI > Windows 表单 调用 我的表格
在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);
}
在配置属性 > 链接器 > 高级下我设置了条目指向到main
在配置属性 > 链接器 > 系统下我设置了子系统 至 Windows (/SUBSYSTEM/WINDOWS)
编译(调试配置): 编译没有 errors/warnings
运行: 运行没有任何问题。
现在让我们尝试将 afxwin.h 添加到 MyForm.cpp:
#include <afxwin.h>
在配置属性>常规下,我将MFC的使用设置为在共享 DLL 中使用 MFC
编译(调试配置): 编译没有 errors/warnings
运行: 应用甚至无法启动,它只是显示 调试断言失败 表达式错误 _CrtIsValidHeapPointer(块)
在配置属性 > 链接器 > 高级下我删除了条目Point值(我之前设置为main)
编译(调试配置): 编译没有 errors/warnings
运行: 应用程序甚至无法启动,它不再显示 Debug Assertion Failed 但 System.AccessViolationException 在未知模块中 和 "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
afxwin.h
怎么可能在 VS2015 中给出所有这些问题,而在 VS2013 中却没有。
有什么办法可以修复它,而无需返回到 VS2013?
James McNellis 为 VS2015 重写了 C 运行时库。他是 C++ 的忠实粉丝,他编写的新代码存在 C++ 程序中常见的慢性 SIOF 问题。 Static Initialization Order 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 让您的程序再次 运行。它是否实际上正确是相当值得怀疑的。这患有与大型框架相关的 "Who is the Boss" 综合症。不要依赖任何 MFC window 才能正常工作,因为它是 Winforms 正在调度消息。但是你应该在 VS2013 中也遇到过这个问题。 "Don't do it" 是唯一可靠的建议。