Утверждение MFC для работы в глобальных деструкторах - PullRequest
2 голосов
/ 21 мая 2019

Я пишу приложение MFC GUI для Visual Studio 2017. И я, естественно, использовал его макросы 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 произвел это.

(Это происходит потому, что функция MessageBox, которая используется внутри ASSERT, не может отображать диалоговое окно, когда процесс завершается.)

Для решения этой проблемы я использовал 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, кажется, показывает диалоговое окно подтверждения при остановке процесса от выхода:

enter image description here* * 1030

Это не дает мне возможности прерваться, если я запускаю свой процесс под отладчиком VS 2017.

У кого-нибудь есть решение, где я могу:

  • Разорвать мой процесс графического интерфейса.
  • Отображение диалогового окна подтверждения.
  • У меня есть возможность вызывать мой JIT-отладчик, если я запускаю процесс под ним.

PS. Я не спрашиваю о регистрации ошибок текстового файла здесь.

1 Ответ

2 голосов
/ 22 мая 2019

Я нашел решение вскоре после того, как опубликовал этот вопрос.Вот оно:

#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

Я оставлю этот вопрос на тот случай, если у кого-то есть идея получше.

...