Почему деструктор не вызывается, когда я нажимаю кнопку закрытия на консоли?

У меня есть приложение командной строки в Windows 7. Оно состоит в основном из бесконечного цикла. Когда я нажимаю кнопку закрытия окна консоли командной строки, оно мгновенно закрывается. Однако я закрываю соединение с базой данных SQLite в деструкторе, поэтому я боюсь, что база данных может быть повреждена. Даже если нет, я хотел бы иметь возможность правильно завершить свой объект (возможно, записав что-то в файл, зарегистрировавшись и т. д.).

Могу ли я как-то убедиться, что мой деструктор вызывается? Что именно произойдет, если я закрою окно? Есть ли более «мягкий» способ закрыть программу?


person Fabian    schedule 15.06.2015    source источник


Ответы (1)


В консольном приложении нет цикла сообщений, в котором вас просят выйти, однако Windows дает вам возможность зарегистрировать функцию для получения некоторых уведомлений, которые вам могут понадобиться. Одним из них является уведомление об закрытии.

Прежде всего объявите функцию, которую Windows будет вызывать для этой цели, с прототипом, заданным HandlerRoutine:

BOOL WINAPI ConsoleHandlerRoutine(DWORD dwCtrlType) {
    if (CTRL_CLOSE_EVENT == dwCtrlType) {
        return TRUE;
    }

    return FALSE;
}

Теперь зарегистрируйте эту функцию, используя SetControlCtrlHandler, прежде чем вы начнете свой цикл:

int main(int argc, char* argv[])
{
    if (FALSE == SetConsoleCtrlHandler(ConsoleHandlerRoutine, TRUE)) {
        // Cannot register your handler? Check GetLastError()
    }

    while (true)
    {
        // This is your loop
    }

    return 0;
}

Это сделано. Вы можете явно удалить объекты, которые хотите удалить, или просто установить флаг, который разорвет ваш бесконечный цикл.

Обратите внимание, что вы получите больше событий (выключение Windows CTRL_SHUTDOWN_EVENT, выход пользователя из системы CTRL_LOGOFF_EVENT, прерывание работы пользователя CTRL_C_EVENT, закрытие CTRL_CLOSE_EVENT), обработайте то, что вам нужно/хотите.

person Adriano Repetti    schedule 15.06.2015
comment
... на самом деле я не уверен, что вы можете установить флаг, разве вам не нужно завершать очистку перед выходом из ConsoleHandlerRoutine? - person Harry Johnston; 16.06.2015
comment
@ГарриДжонстон: Да. Если Handler возвращает TRUE, процесс немедленно завершается. Если он возвращает FALSE, вызывается следующий зарегистрированный Handler и так далее, пока один из них не вернет TRUE или не будет достигнуто значение по умолчанию Handler, в любом случае процесс завершается. И вы должны учитывать, что Handler вызывается в контексте своего собственного потока, поэтому убедитесь, что его код потокобезопасен. - person Remy Lebeau; 16.06.2015
comment
Я предполагаю, что во многих случаях для процедуры обработчика проще всего установить флаг, а затем просто спать, пока основной поток не завершит процесс. - person Harry Johnston; 16.06.2015
comment
Я как Йода себя чувствовал. Тот день. - person Adriano Repetti; 10.01.2018