什么会导致GetLastError()==0的CreateDialogIndirect()延迟启动失败 我在MFC C++ X86应用程序中遇到了一个非常奇怪的问题,其中对话框在一段时间后开始失败。应用程序可以正常工作几个小时,之后一些对话框无法打开。没有明显的事件或活动高峰可以合理解释故障开始出现的原因。这个问题影响到许多(但不是所有)对话框,其复杂性从简单的登录对话框到具有许多复杂控件的复杂业务对话框不等。可以工作的对话框的复杂性也各不相同。有效的对话框和失败的对话框之间没有明显的区别

什么会导致GetLastError()==0的CreateDialogIndirect()延迟启动失败 我在MFC C++ X86应用程序中遇到了一个非常奇怪的问题,其中对话框在一段时间后开始失败。应用程序可以正常工作几个小时,之后一些对话框无法打开。没有明显的事件或活动高峰可以合理解释故障开始出现的原因。这个问题影响到许多(但不是所有)对话框,其复杂性从简单的登录对话框到具有许多复杂控件的复杂业务对话框不等。可以工作的对话框的复杂性也各不相同。有效的对话框和失败的对话框之间没有明显的区别,c++,winapi,mfc,C++,Winapi,Mfc,当我在AfxWndProc(wincore.cpp内部)上放置一个断点并仅在输入CreateDialogIndirect()后激活它时,会按如下方式命中它: 良好行为(破裂前的前几个小时): WM_NCCREATE(0x0081)-返回1 WM_NCCALCSIZE(0x0083)-返回0 WM_CREATE(0x0001)-返回0 WM_大小(0x0005)-返回0 WM_移动(0x0003)-返回0 WM_SETFONT(0x0030)-返回0 WM_INITDIALOG(0x0110)-返

当我在AfxWndProc(wincore.cpp内部)上放置一个断点并仅在输入CreateDialogIndirect()后激活它时,会按如下方式命中它:

良好行为(破裂前的前几个小时):
WM_NCCREATE(0x0081)-返回1
WM_NCCALCSIZE(0x0083)-返回0
WM_CREATE(0x0001)-返回0
WM_大小(0x0005)-返回0
WM_移动(0x0003)-返回0
WM_SETFONT(0x0030)-返回0
WM_INITDIALOG(0x0110)-返回1

在此之后,在CreateDialogIndirect()最终返回有效的hWnd和GetLastError()之前,还有一系列其他消息(可能与正在初始化的单个控件有关)

一旦进入不良状态:
WM_NCCREATE(0x0081)-返回1
WM_NCCALCSIZE(0x0083)-返回0
WM_CREATE(0x0001)-返回0
WM_大小(0x0005)-返回0
WM_移动(0x0003)-返回0
WM_SETFONT(0x0030)-返回0
WM_UAHDESTROYWINDOW(0x0090)-返回0
WM_DESTROY(0x0002)-返回0
WM_NCDESTROY(0x0082)-返回0
CreateDialogIndirect()返回null,GetLastError()返回0

我调查了以下潜在原因:

  • GDI句柄:这似乎很低(小于600)
  • 无效/错误控件:所有对话框最初都工作,因此不太可能是由于自定义控件或对话框模板造成的
  • 类被注销:我在MFC UnregiserClass调用中尝试了断点。它们仅在应用程序退出时触发
一些可能相关(或不相关)的其他背景信息:

  • 这是一个win32 MFC x86动态链接应用程序
  • 应用程序相当复杂(即50多个对话框、复杂的网格控件、传入数据的后台流、多个模块——每个模块都在自己的DLL中、动态加载语言资源DLL)
  • 原始代码库已通过MSVC的多个版本进行了升级(从2005年到2019年)
  • 我们在一个使用VS2013构建的实例上遇到了这个问题,但后来将该项目升级到VS2019(VC16),但没有成功
  • 我们有其他客户机运行使用VS2013构建的基本相同的代码库(不同的分支),他们没有遇到这个问题
  • 在Win7和Win10上都可以看到该问题
任何其他线索或潜在的调查途径将不胜感激


编辑:此后,我们发现只有包含文本编辑(CEdit)控件的对话框出现故障,而且即使应用程序内存相对较低,也似乎是由于内存问题

可能你泄露了资源。GDI或许可以处理。调用CreateDialogIndirect后,没有迹象表明GetLastError是有意义的,顺便说一句,它没有返回任何值。@dav:不幸的是,文档是错误的。自从移动到DOCS.MICROSULT.com,C++文档就受限于表达.NETCLR能够表达的内容。不幸的是,预处理器宏就是这种情况的受害者;它们都列出了返回类型
void
<但是,code>CreateDialogIndirect[A | W]会返回返回的内容,即
HWND
。它还设置了发生故障时的最后一个错误代码。