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 断言在全局析构函数中工作的主要内容,如果未能解决你的问题,请参考以下文章

在 MFC 中调用 EndDialog() 时,类析构函数何时触发?

gcov 和全局析构函数

Excel VBA 对象构造函数和析构函数

CImage析构函数问题?

c++ 析构函数 是在啥时候执行

C++ 构造函数 & 析构函数