【问题标题】:MFC assertion to work in global destructorsMFC 断言在全局析构函数中工作
【发布时间】: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:你试过了吗?

标签: c++ winapi visual-studio-2017 mfc assert


【解决方案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

如果有人有更好的想法,我会保留这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 2011-04-18
    相关资源
    最近更新 更多