Завершить приложение И вызвать деструкторы локальных объектов - PullRequest
8 голосов
/ 11 апреля 2011

У меня есть несколько объектов в стеке в основной функции:

int main(...)
{
   CFoo foo;
   CBar bar;
}

Кроме того, у меня есть функция, которая отслеживает ошибки в моем приложении:

void Err(std::string msg)
{
   SomehowLogErrorMessage(msg);
   exit(1);
}

Функция Err определенно полезна, когда я должен сообщить о фатальной ошибке. Я просто регистрирую ошибку и закрываю приложение - оно не может восстановиться после таких ошибок. Однако завершение с помощью «exit ()» не вызывает деструкторы foo и bar - поведение, которое я действительно ожидал (но ошибся). "abort ()" тоже не помогает. Также, Я не могу использовать исключения , чтобы перехватить их в main (). Есть ли другой способ реализовать функцию Err так, чтобы она закрывала приложение и правильно очищала объекты стека? Или я должен каким-то образом переработать обработку ошибок?

Спасибо!


p.s. Кстати, я не могу отправить сообщение WM_QUIT в главное окно? Я не очень хорош с WinAPI, но мое приложение чисто Win32, и моя функция Err () может получить указатель на мое главное окно. Будет ли это работать?

Ответы [ 5 ]

3 голосов
/ 11 апреля 2011

Не без исключений или обычного возврата из Err до уровня стека вызововВам нужно размотать стопку.

2 голосов
/ 11 апреля 2011

Есть еще С setjmp и longjmp. Он должен вернуть вас к main, поэтому программа будет завершаться как обычно после выхода из области действия main, и в этом случае механизм деструктора C ++ уничтожит ваши локальные объекты в main.

Конечно, использование longjmp не приветствуется в C ++ по веским причинам. Он пропускает любые другие функции в стеке, поэтому он действительно работает только для нескольких объектов стека в main.

Возможно, вам будет проще разместить ваши объекты в куче и delete вручную в Err.

1 голос
/ 11 апреля 2011

Существует два основных способа распространения ошибок в C ++: исключения (которые вы, казалось бы, произвольно исключили) и коды возврата.

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

Также учтите, что если ваша программа находится в фатальном состоянии, деструкторы действительно смогут очиститься ожидаемым образом?Что если состояние объекта имеет недостатки и не может быть исправлено должным образом?Вместо вызова exit вы можете вызвать abort, что по крайней мере оставит ядро, чтобы помочь диагностировать проблему, если вы попали в плохое состояние.Для фатальных ошибок, когда исключения недоступны, это разумный выбор.

0 голосов
/ 11 апреля 2011

Я бы переработал вашу обработку ошибок. Самое простое, что нужно сделать - это вернуть управление на main и позволить ему выполнить обычную очистку. Исключения предоставляют эту возможность через разматывание стека, но вы не можете использовать исключения. ОК, хорошо. Иногда вы просто не можете использовать исключения.

Поэтому вместо Err попытайтесь закрыть программу, Err зарегистрируйте ошибку и верните код ошибки. В идеале Err в любом случае не должно выполнять две работы, которые вы пытаетесь заставить сделать это: 1) Зарегистрируйте ошибку, 2) Изящно завершите работу приложения.

Если ваше приложение является многопоточным, вам может быть отказоустойчиво. В потоке регистрации ошибок сообщайте о событии die. Пусть главный поток ожидает этого события вместе со всем, что ожидает (или вводит в него задание через QueueUserAPC или подобное). Когда событие сигнализирует, закройте приложение.

0 голосов
/ 11 апреля 2011

Полагаю, Exit немедленно прекратит работу.Чтобы увидеть поведение, которое вы ожидаете, foo и bar должны выйти за рамки.Это означает, что основная функция должна обычно заканчиваться возвращаемым значением.Вместо того, чтобы вызывать Exit() из вашей функции Err, вам нужно найти способ вернуться к вашей основной функции и позволить ей нормально вернуться со значением ошибки.

...