MFC 断言在全局析构函数中工作
Posted
技术标签:
【中文标题】MFC 断言在全局析构函数中工作【英文标题】:MFC assertion to work in global destructors 【发布时间】:2019-05-21 20:48:34 【问题描述】:我正在使用 Visual Studio 2017 编写一个 MFC GUI 应用程序。我很自然地使用它的 ASSERT/VERIFY 宏来进行一些调试器代码检查。但不幸的是,这些在全局析构函数中不起作用。例如,如果我有这样的事情:
struct MY_STRUCT
HANDLE hHandle;
MY_STRUCT()
: hHandle(NULL)
~MY_STRUCT()
//Make sure handle was released
ASSERT(hHandle == NULL);
;
//On the global scale
MY_STRUCT mys;
如果MY_STRUCT
的析构函数中的断言被触发,它只会产生一个警告蜂鸣声,但不会显示断言对话框,进程将终止。所以很难看出是哪个ASSERT
制作的。
(这是因为ASSERT
内部使用的MessageBox
函数在进程终止时无法显示对话窗口。)
为了解决这个问题,我将FatalAppExit
API 用于我自己定义的那个宏的版本:
#ifdef _DEBUG
#define ASSERT2(f) if(!(f))\
\
char __buffer123456789[256*4];\
wsprintfA(__buffer123456789, "ASSERTION!!!\nFile: %s\nLine: %d\nGetLastError() = %d", __FILE__, __LINE__, ::GetLastError());\
FatalAppExitA(0, __buffer123456789);\
#else
#define ASSERT2(f) ((void)0)
#endif
即使我的ASSERT2
似乎在停止进程退出时显示了一个断言对话框:
如果我在 VS 2017 调试器下运行我的进程,它不会让我选择中断。
有没有人可以提供解决方案:
中断我的 GUI 进程。 显示断言对话框。 如果我在其下运行进程,可以选择调用我的 JIT 调试器。PS。我在这里没有询问有关文本文件错误记录的问题。
【问题讨论】:
建议您在程序关闭期间使用OutputDebugString
进行日志记录,请参阅:msdn.microsoft.com/en-us/library/windows/desktop/…
和DebugBreak
进入调试器(如果已附加)请参阅:docs.microsoft.com/en-us/windows/desktop/api/debugapi/…
@RichardCritten:哦,开枪,我刚刚意识到我可以使用IsDebuggerPresent()
来检查那个宏,如果它返回true
,那么在调用FatalAppExit
之前调用DebugBreak()
。跨度>
在这里运行MessageBoxW真的没问题。进程尚未终止。在调用 ExitProcess
之前调用的 exe 析构函数。队列中可能是QW_QUIT
的另一个任务。需要先 MSG 味精; while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)); 循环
@RbMm:你试过了吗?
【参考方案1】:
我在发布此问题后不久就找到了解决方案。这里是:
#ifdef _DEBUG
#define ASSERT2(f) if(!(f))\
\
if(::IsDebuggerPresent()) ::DebugBreak(); \
char __buffer123456789[256*4];\
wsprintfA(__buffer123456789, "ASSERTION!!!\nFile: %s\nLine: %d\nGetLastError() = %d", __FILE__, __LINE__, ::GetLastError());\
FatalAppExitA(0, __buffer123456789);\
#else
#define ASSERT2(f) ((void)0)
#endif
#ifdef _DEBUG
#define VERIFY2(f) ASSERT2(f)
#else
#define VERIFY2(f) ((void)(f))
#endif
如果有人有更好的想法,我会保留这个问题。
【讨论】:
以上是关于MFC 断言在全局析构函数中工作的主要内容,如果未能解决你的问题,请参考以下文章