У C і C ++, яка різниця між exit()
і abort()
? Я намагаюся закінчити свою програму після помилки (не виняток).
У C і C ++, яка різниця між exit()
і abort()
? Я намагаюся закінчити свою програму після помилки (не виняток).
Відповіді:
abort()
виходить із програми без виклику функцій, зареєстрованих atexit()
спочатку, та без виклику спочатку деструкторів об’єктів. exit()
робить обидва перед виходом із програми. Однак він не викликає деструктори для автоматичних об'єктів. Так
A a;
void test() {
static A b;
A c;
exit(0);
}
Зруйнує a
і b
належним чином, але не закличе деструкторів c
. abort()
не викликав би руйнівників жодного об'єкта. Оскільки це прикро, Стандарт C ++ описує альтернативний механізм, який забезпечує належне припинення:
Об'єкти з автоматичною тривалістю зберігання знищуються в програмі, функція якої
main()
не містить автоматичних об'єктів і виконує виклик доexit()
. Контроль можна передати безпосередньо такомуmain()
, кинувши виняток, який потрапив уmain()
.
struct exit_exception {
int c;
exit_exception(int c):c(c) { }
};
int main() {
try {
// put all code in here
} catch(exit_exception& e) {
exit(e.c);
}
}
Замість дзвінків exit()
організуйте цей код throw exit_exception(exit_code);
замість цього.
аборт надсилає сигнал SIGABRT, вихід просто закриває програму, виконуючи звичайну очистку.
Ви можете обробляти сигнал переривання, як хочете, але поведінка за замовчуванням - це закрити програму, а також кодом помилки.
аборт не буде виконувати знищення об'єктів ваших статичних і глобальних членів, але вихід буде.
Звичайно, якщо програма повністю закрита, операційна система звільнить незапалену пам'ять та інші ресурси.
В обох переривання і вихід завершення програми (якщо ви не перевизначити поведінку за замовчуванням), код повернення буде повернений в батьківський процес , який почав свій додаток.
Дивіться наступний приклад:
SomeClassType someobject;
void myProgramIsTerminating1(void)
{
cout<<"exit function 1"<<endl;
}
void myProgramIsTerminating2(void)
{
cout<<"exit function 2"<<endl;
}
int main(int argc, char**argv)
{
atexit (myProgramIsTerminating1);
atexit (myProgramIsTerminating2);
//abort();
return 0;
}
Коментарі:
Якщо аборт не коментується: нічого не друкується і деструктор якогось об'єкта не буде викликаний.
Якщо аборт буде прокоментовано як вище: буде викликано якийсь деструктор об'єкта, ви отримаєте такий вихід:
функція виходу 2
функція виходу 1
Коли програма викликає exit
(), відбувається таке:
atexit
функцією, виконуютьсяtmpfile
, видаляютьсяФункція abort
() надсилає SIGABRT
сигнал поточному процесу, якщо його не зафіксували, програма припиняється без гарантії, що відкриті потоки змиваються / закриваються або tmpfile
видаляються тимчасові файли через , atexit
зареєстровані функції не викликаються, а не- нульовий статус виходу повертається хосту.
З сторінки керівництва exit ():
Функція exit () викликає нормальне завершення процесу, і значення статусу & 0377 повертається батьківському.
З сторінки посібника про переривання ()
Аборт () спочатку розблокує сигнал SIGABRT, а потім піднімає цей сигнал для процесу виклику. Це призводить до ненормального припинення процесу, якщо сигнал SIGABRT не зачеплений і обробник сигналу не повернеться.
abort
посилає SIGABRT
сигнал. abort
не повертається до абонента. Обробник за замовчуванням для SIGABRT
сигналу закриває програму. stdio
потоки файлів промиваються, потім закриваються. Однак деструктори для екземплярів класу C ++ не є (не впевнені в цьому - можливо, результати не визначені?).
exit
має свої зворотні дзвінки, встановлені з atexit
. Якщо зворотні виклики вказані (або лише один), вони викликаються в порядку, зворотному їх порядку реєстрації (як стек), тоді програма виходить. Як і у випадку abort
, exit
не повертається до абонента. stdio
потоки файлів промиваються, потім закриваються. Також викликаються деструктори для екземплярів класу C ++.