ExitInstance не вызывается в приложении MFC - PullRequest
1 голос
/ 06 июля 2010

До сих пор мне никогда не требовалось использовать Winapp ExitInstance () для большого приложения MFC (Single Document Interface, если это важно), над которым я работаю. Но сейчас я делаю это, главным образом, для очистки памяти, выгрузки некоторых библиотек DLL и т. Д. Вскоре я узнал об очевидных утечках памяти и о том, что ExitInstance не вызывался. Я что-то упустил очевидное? Нужно ли вручную что-то добавлять в карту сообщений, чтобы убедиться, что мое переопределение ExitInstance вызвано?

Полагаю, я могу провести уборку в другом месте, но это лучшее место, если я смогу запустить его. Интересно, что я обнаружил довольно много примеров этого, набрав в Google такие строки, как «ExitInstance никогда не вызывал» и тому подобное, и ни в одном случае не было предложено никаких реальных ответов. Приложение обычно закрывается, когда кто-то нажимает кнопку закрытия или «Выход» из меню «Файл», и OnClose () окна мэйнфрейма, безусловно, всегда вызывается. Я даже попытался заставить вещи, поставив AfxGetMainWnd () -> DestroyWindow (); в этом событии OnClose () для мэйнфрейма, но я все еще не могу заставить ExitInstance () действительно работать. Может быть, это просто большая фиктивная функция? Или, может быть, Я просто большая кукла? : -)

Ответы [ 5 ]

1 голос
/ 15 ноября 2012

У меня была такая же проблема. Оказывается, это было вызвано тем, что некоторые сообщения были предварительно переведены объектом CWinApp после уничтожения мэйнфрейма. Во время этой обработки будет произведена проверка достоверности, и он просто выйдет из строя, а не выйдет через обычный экземпляр выхода.

Переопределение приложения PreTranslate message и немедленный возврат, когда не было главного кадра, решили проблему.

BOOL CYourAppClass::PreTranslateMessage( MSG* pMsg )
{
    // If the main window has gone away there is no need to do pre-translation.
    // If the pre-translation were allowed to proceed the
    //  CWinAppEx::PreTranslateMessage may bail out without calling
    /// the app's ExitInstance nor destructing the app object.
    if ( !m_pMainWnd )
        return FALSE;

return CWinAppEx::PreTranslateMessage( pMsg );
}
1 голос
/ 17 мая 2011

У меня была похожая проблема с вами ... моя была вызвана смешением Unicode и встроенного кода MBCS .... может быть, это было вашей основной причиной?

Мне пришлось преобразовать приложение MBCS в Unicode, но преобразовать весь проект было невозможно, поэтому мне пришлось смешивать скомпилированный код Unicode (приложение) и код, скомпилированный MBCS (библиотеки DLL).

Некоторые из библиотек MBCS были библиотеками расширения MFC, другие были обычными DLL.

Одна из библиотек расширения MFC содержала ресурсы (список растровых изображений и общие диалоговые окна).

Я не конвертировал DLL в UNICODE, потому что в ней было много зависимых DLL, которые также пришлось бы конвертировать, и, кроме того, мне не требовались элементы управления в общих диалоговых окнах для поддержки текста Unicode.

Так что я сохранил DLL как MBCS и использовал AfxSetResourceHandle до использования любого класса в DLL MBCS, который использовал ресурсы ..... это было сделано для того, чтобы ресурсы извлекались из DLL напрямую, а не через ресурс MFC цепочка, потому что MFC не может найти ресурсы не-Unicode в противном случае.

Полагаю, MFC не нравится, когда у вас есть смесь скомпилированного кода Unicode и не-Unicode, содержащего ресурсы ..... поиск в цепочке ресурсов завершается неудачно (я думаю, что это как-то связано с преобразованием идентификаторов ресурсов) в строку идентификатора, т.е. через MAKEINTRESOURCE).

Я сделал основное приложение UNICODE и убедился, что заголовки C ++ классов в DLL-библиотеках MBCS использовали CStringA в прототипах функций или принимали широкие строки и выполняли преобразование внутри.

Я обнаружил, что мое приложение не будет корректно завершать работу ... оно будет оставаться в вызове MFC CWinThread :: PumpMessage / AfxInternalPumpMessage (), а ExitInstance никогда не будет вызываться.

Чтобы решить эту проблему, в моем CMainFrame :: OnDestroy () я поместил следующее как последние 2 утверждения:

void CMainFrame::OnDestroy() 
{
    ....

    CFrameWnd::OnDestroy();

    AfxPostQuitMessage(0);
}
0 голосов
/ 31 января 2018

Другая возможность заключается в том, что в процессе завершения работы происходит ошибка подтверждения.Например, разрушая окно.Я обнаружил, что когда это происходит, ExitInstance также пропускается.

Итак, перед закрытием приложения очистите окно журнала вывода / отладки и посмотрите, печатается ли такое сообщение.Если это так, решите проблему и посмотрите, будет ли вызван ExitInstance снова.

0 голосов
/ 31 января 2014

У меня была точно такая же проблема.

В моем случае проблема была решена путем переопределения PostNcDestroy в CMainFrame. Кажется, что обработка этого последнего сообщения в главном окне заставляет все это работать:

virtual void PostNcDestroy();

void CMainFrame::PostNcDestroy()
{
}
0 голосов
/ 09 января 2014

Вы говорите, что «OnClose () окна мэйнфрейма определенно всегда вызывается».У меня была проблема с одним из моих приложений MFC;Я поместил некоторый код очистки потока в обработчик событий OnClose () моего окна, и он не вызывался.После некоторой боли я поместил код очистки потока в обработчик событий OnDestroy (), и теперь он всегда вызывается.Поэтому вы можете проверить, всегда ли вызывается ваш обработчик события OnClose ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...