Visual Studio 2015 Windows 窗体应用程序中的 afxwin.h 问题
Posted
技术标签:
【中文标题】Visual Studio 2015 Windows 窗体应用程序中的 afxwin.h 问题【英文标题】:afxwin.h issues in Visual Studio 2015 Windows Form App 【发布时间】:2016-02-23 11:04:31 【问题描述】:前段时间,我编写了一个 C++ CLI Windows Form 应用程序,它在 Visual Studio 2013 中编译得很好。现在我想在 Visual Studio 2015 Update 1 中重新编译它,但我遇到了一个问题,经过数小时的测试我发现罪魁祸首是afxwin.h
。
TL;DR - 有什么方法可以在使用 Visual Studio 2015 编译的 Windows 窗体应用程序中使用 stdafx.h
(所以 afxwin.h
和所有其他导入)而不需要启动时应用崩溃?
这是重现我在应用中遇到的相同问题的方法。
由于 Windows 窗体在 VS2015 中不再可用作项目模板,我创建了一个名为 Test
的 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);
在 Configuration Properties > Linker > Advanced 我将 Entry Point 设置为 main
在 Configuration Properties > Linker > System 我将 SubSystem 设置为 Windows (/SUBSYSTEM/窗口)
编译(调试配置):编译时没有错误/警告
RUN:运行没有任何问题。
现在让我们尝试将 afxwin.h 添加到 MyForm.cpp:
#include <afxwin.h>
在配置属性 > 常规我将使用MFC设置为在共享DLL中使用MFC
编译(调试配置):编译时没有错误/警告
RUN:应用程序甚至无法启动,它只是在表达式 _CrtIsValidHeapPointer(block)
中显示 Debug Assertion Failed 错误现在要修复这个错误,我发现有必要删除 Entry Point,所以:
在 Configuration Properties > Linker > Advanced 我删除了 Entry Point 值(我之前设置为 主要)
编译(调试配置):编译时没有错误/警告
RUN:应用程序再次无法启动,它不再显示Debug Assertion Failed,而是显示System.AccessViolationException in an unknown module和“试图读取或写入受保护的内存。这通常表明其他内存已损坏。"
这些是我在我的应用程序中遇到的错误,我想知道简单地包含afxwin.h
怎么可能在 VS2015 中出现所有这些问题,而在 VS2013 中却没有。
在不回到 VS2013 的情况下,我可以做些什么来修复它?
【问题讨论】:
【参考方案1】:James McNellis 为 VS2015 重写了 C 运行时库。他是 C++ 的忠实粉丝,他编写的新代码遭受了 C++ 程序中常见的慢性 SIOF 问题。 Static Initialization Order Fiasco 肯定也存在于您的 VS2013 项目中,但碰巧没有字节,原始 CRT 代码已暴露于 SIOF 多年,因此可能表现得更好。
在这种情况下非常难以调试,失败的代码来自名为 thread_safe_statics.cpp 的安装中未包含的 CRT 源代码文件。鉴于没有可查看的源代码,但无法 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 中也遇到过这个问题。 “不要这样做”是唯一可靠的建议。
【讨论】:
感谢您的详细解释,您提供的代码解决了问题,我的应用程序恢复了工作!请注意:Linker > Advanced 配置中的Entry Point 字段empty 是必要的,否则Debug Assertion Failed再次出现错误。 对不起,你是对的,我确实使用默认值进行了测试。 CRT 初始化必须在前,MFC 的 WinMain 必须在后。以上是关于Visual Studio 2015 Windows 窗体应用程序中的 afxwin.h 问题的主要内容,如果未能解决你的问题,请参考以下文章
在 Visual Studio Window Form 的面板上使用不透明度的任何技巧?
如何在使用WIN10 Visual Studio 2015 编译FlightGear源码(2020.1.1版本)
如何在使用WIN10 Visual Studio 2015 编译FlightGear源码(2020.1.1版本)
如何在 Windows 10 上使用 Visual Studio 2015 x64 配置和构建 Tesseract OCR C++