прервать, завершить или выйти?



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

1005   6  
c++

6 ответов:

мой совет был бы не использовать ни один из них. Вместо этого поймайте исключения, которые вы не можете обработать в main (), и просто вернитесь оттуда. Это означает, что вы гарантируете, что размотка стека происходит правильно и все деструкторы вызываются. Другими словами:

int main() {
    try {
       // your stuff
    }
    catch( ... ) {
       return 1;    // or whatever
    }
}
  • отмена указывает на "ненормальный" конец программы и вызывает сигнал POSIX SIGABRT, что означает, что любой обработчик, который вы зарегистрировали для этого сигнала, будет вызван, хотя программа все равно завершит послесловие в любом случае. Обычно вы бы использовали abort в программе C для выхода из непредвиденного случая ошибки, когда ошибка, скорее всего, будет ошибкой в программе, а не чем-то вроде плохого ввода или сбоя сети. Для например, вы могли бы abort Если в структуре данных был обнаружен нулевой указатель, когда это логически никогда не должно происходить.

  • выход указывает на "нормальный" конец программы, хотя это все еще может означать сбой (но не ошибку). Другими словами, вы можете exit С кодом ошибки, если пользователь дал сигнала, который не может быть обработан, или файл не может быть прочитан. Код выхода 0 указывает на успех. exit также вызовы обработчиков прежде чем он завершит программу. Они зарегистрированы в atexit и on_exit функции.

  • std:: terminate это то, что автоматически вызывается в программе C++, когда есть необработанное исключение. Это, по сути, в C++ эквивалентно abort, предполагая, что вы сообщаете о всех своих исключительных ошибок с помощью исключений. Это вызывает обработчик, который устанавливается std::set_terminate функция, которая по умолчанию просто вызывает abort.

в C++ вы обычно хотите избежать вызова abort или exit при ошибке, так как вам лучше выбросить исключение и позволить коду дальше вверх по стеку вызовов решить, подходит ли завершение программы. Независимо от того, используете ли вы exit для успеха это вопрос обстоятельств - имеет ли смысл заканчивать программу где-то еще, кроме оператора return в main.

std::terminate следует считать a последние отчеты об ошибках инструмента, даже в C++. Проблема с std::terminate это то, что обработчик завершения делает не есть доступ к исключению, которое прошло без обработки, так что нет никакого способа сказать, что это было. Обычно вам гораздо лучше обернуть всю основную часть в try { } catch (std::exception& ex) { } блок. По крайней мере, тогда вы можете сообщить дополнительную информацию об исключениях, полученных из std::exception (хотя конечно исключения, которые не вытекают из std::exception все равно останется необработанным).

обертывание тела main на try { } catch(...) { } не намного лучше, чем установка обработчика завершения, потому что снова у вас нет доступа к рассматриваемому исключению. Edit: согласно ответу Нила Баттерворта, есть преимущество в том, что стек разматывается в этом случае, что (несколько удивительно) неверно для необработанного исключения.

std::abort и std:: exit (и еще:std::_Exit, std:: quick_exit) - это просто функции более низкого уровня. Вы используете их, чтобы сказать программе, что именно вы хотите, чтобы она делала: какие деструкторы (и если) вызывать, какие другие функции очистки вызывать, какое значение возвращать и т. д.

std:: terminate-это абстракция более высокого уровня: она вызывается (либо во время выполнения, либо вами), чтобы указать, что произошла ошибка в программе и что по какой-то причине ее невозможно обработать, бросив исключение. Необходимость в этом обычно возникает, когда ошибка возникает в самом механизме исключения, но вы можете использовать его в любое время, когда вы не хотите, чтобы ваша программа продолжалась после данной ошибки. Я составил полный список ситуаций, когда std::terminate называется в моем посте. Не указано, что делает std::terminate, потому что вы контролируете его. Вы можете настроить поведение, зарегистрировав любые функции. Ограничения у вас есть, что функция не может вернитесь обратно на сайт ошибки, и он не может выйти через исключение, но технически вы даже можете запустить свой насос сообщений внутри. Список полезных вещей, которые вы можете сделать внутри, см. мой пост.

в частности, обратите внимание, что std::terminate считается обработчиком исключений в контекстах, где std:: terminate вызывается из-за брошенного исключения, которое не может быть обработано, и вы можете проверить, что такое исключение, и проверить его с помощью C++11 с помощью std::rethrow_exception и std:: current_exception. Это все в мой пост.

quick_exit () !

если ваша программа многопоточна, то вызов exit() скорее всего, приведет к аварии, потому что global / static std::thread объекты будут пытаться уничтожить, не выходя из своих потоков.

если вы хотите вернуть код ошибки и выход из программы (более или менее), как правило, называют quick_exit() в многопоточных программах. Для аварийного завершения (без возможности указать код ошибки), abort() или std::terminate() можно назвать.

Примечание: quick_exit () не поддерживается MSVC++ до версии 2015 .

  • terminate () вызывается автоматически когда возникает исключение, которое не может быть обработанным. По умолчанию завершить() вызывает abort(). Вы можете установить пользовательский ручка с set_terminate() функция.

    abort () посылает сигнал SIGABRT.

    exit() не обязательно плохо вещь. Он успешно завершает работу приложений и вызовы atexit() функции в порядке ЛИФО. Я не обычно это видно в C++ приложения, однако, я вижу это в многие unix на основе приложения, где это отправляет код выхода в конце. Обычно выход(0) указывает на успешный запуск приложения.

  • terminate оставляет вам возможность зарегистрировать то, что произойдет, когда он будет вызван. Должен быть один из двух других.
  • exit-это обычный выход, позволяющий задать статус выхода. Обработчики, зарегистрированные at_exit () выполняются
  • аборт-это аварийный выход. Единственное, что выполняется-это обработчик сигнала для SIGABRT.

Comments

    Ничего не найдено.