Apa perbedaan antara exit () dan abort ()?

130

Dalam C dan C ++, apa perbedaan antara exit()dan abort()? Saya mencoba untuk mengakhiri program saya setelah kesalahan (tidak terkecuali).

Martin Liversage
sumber

Jawaban:

116

abort()keluar dari program Anda tanpa memanggil fungsi yang didaftarkan menggunakan atexit()terlebih dahulu, dan tanpa memanggil destruktor objek terlebih dahulu. exit()melakukan keduanya sebelum keluar dari program Anda. Itu tidak memanggil destruktor untuk objek otomatis. Begitu

A a;
void test() { 
    static A b;
    A c;
    exit(0);
}

Akan merusak adan bbenar, tetapi tidak akan memanggil destruktor dari c. abort()tidak akan memanggil destruktor dari kedua objek. Karena ini sangat disayangkan, Standar C ++ menjelaskan mekanisme alternatif yang memastikan penghentian dengan benar:

Objek dengan durasi penyimpanan otomatis semuanya dihancurkan dalam program yang fungsinya main()tidak berisi objek otomatis dan mengeksekusi panggilan ke exit(). Kontrol dapat ditransfer langsung ke seperti itu main()dengan melemparkan pengecualian yang tertangkap 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);
    }
}

Alih-alih menelepon exit(), alih-alih mengatur kode itu throw exit_exception(exit_code);.

Johannes Schaub - litb
sumber
2
1 karena, sementara Brian R. Bondy bagus, Anda memang mengangkat masalah batalkan / keluar (bukan penghancur objek tumpukan yang disebut), dan menawarkan alternatif untuk proses C ++ intensif RAII.
paercebal
Saya sedang mencari cara untuk keluar dari program tanpa menelepon dtor dan jawaban Anda adalah apa yang saya cari! Terima kasih
acemtp
Itu tentu saja benar, jika itu benar-benar penting bahwa penghancur benda otomatis Anda tidak dipanggil :-)
Chris Huang-Leaver
Sepengetahuan saya, satu perbedaan lebih lanjut antara jalan keluar dan batal adalah, batal itu bisa (tergantung pada konfigurasi sistem operasi) menyebabkan generasi dump inti.
Dirk Herrmann
33

batalkan mengirim sinyal SIGABRT, keluar hanya menutup aplikasi melakukan pembersihan normal.

Anda dapat menangani sinyal batal sesuka Anda, tetapi perilaku default adalah menutup aplikasi juga dengan kode kesalahan.

batalkan tidak akan melakukan penghancuran objek dari anggota statis dan global Anda, tetapi keluar akan.

Tentu saja meskipun ketika aplikasi ini benar-benar ditutup, sistem operasi akan membebaskan setiap memori yang tidak masuk dan sumber daya lainnya.

Dalam membatalkan dan keluar dari penghentian program (dengan asumsi Anda tidak mengabaikan perilaku default), kode kembali akan dikembalikan ke proses induk yang memulai aplikasi Anda.

Lihat contoh berikut:

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;
}

Komentar:

  • Jika batalkan uncommented: tidak ada yang dicetak dan destruktor dari beberapa objek tidak akan dipanggil.

  • Jika batalkan dikomentari seperti di atas: someobject destructor akan dipanggil Anda akan mendapatkan output berikut:

fungsi keluar 2
fungsi keluar 1

Brian R. Bondy
sumber
Di sini, ini disebut fungsi keluar 2 MAKA fungsi keluar 1. gcc 4, Linux 2.6.
strager
1
Halaman manual untuk atexit mengatakan: "Fungsi [terdaftar menggunakan atexit] dipanggil dalam urutan terbalik; tidak ada argumen yang diteruskan."
strager
@ strager benar, fungsi yang didaftarkan oleh atexit seharusnya dipanggil dalam urutan terbalik ketika salah satu keluar dipanggil atau pengembalian utama.
Robert Gamble
Menjalankan tes dan tampaknya destruktor untuk instance global dipanggil setelah semua callback atexit.
strager
+1 untuk mengingatkan orang bahwa OS pada akhirnya akan membebaskan semua sumber daya yang dialokasikan bahkan setelah panggilan abort ().
Fingolfin
10

Hal-hal berikut terjadi ketika suatu program memanggil exit():

  • Fungsi yang didaftarkan oleh atexitfungsi dieksekusi
  • Semua aliran terbuka memerah dan tertutup, file yang dibuat oleh tmpfiledihapus
  • Program berakhir dengan kode keluar yang ditentukan untuk host

Fungsi abort() mengirimkan SIGABRTsinyal ke proses saat ini, jika tidak tertangkap program dihentikan tanpa jaminan bahwa stream terbuka memerah / tertutup atau bahwa file sementara yang dibuat melalui tmpfiledihapus, atexitfungsi terdaftar tidak dipanggil, dan non- status keluar nol dikembalikan ke host.

Robert Gamble
sumber
hmm standar mengatakan program hanya tidak dihentikan jika penangan sinyal "tidak kembali". Anda cukup baik dengan C. dapatkah Anda membayangkan skenario apa pun yang memungkinkannya melanjutkan eksekusi normal tanpa kembali? saya membayangkan longjmp, tapi saya tidak yakin tentang bagaimana berperilaku di penangan sinyal.
Johannes Schaub - litb
Secara umum, memanggil longjmp dari pengatur sinyal tidak ditentukan tetapi ada kasus khusus untuk ketika sinyal dihasilkan dengan kenaikan / batalkan jadi saya kira ini akan secara teoritis mungkin meskipun saya tidak berpikir saya pernah melihatnya melakukannya. Sekarang saya harus mencobanya;)
Robert Gamble
1
Ini sepertinya berhasil (dipecah menjadi beberapa posting karena batasan 300 char): #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <setjmp.h> volatile sig_atomic_t do_abort = 1; jmp_buf env; membatalkan abort_handler (int i) {do_abort = 0; longjmp (env, 1);}
Robert Gamble
int main (void) {setjmp (env); puts ("At setjmp"); if (do_abort) {signal (SIGABRT, abort_handler); menempatkan ("Memanggil batalkan"); menggugurkan(); } menempatkan ("Tidak membatalkan!"); return 0; }
Robert Gamble
Pada Ubuntu 7.04 ini dicetak: Di setjmp Memanggil batal Di setjmp Tidak batal!
Robert Gamble
5

Dari halaman manual exit ():

Fungsi exit () menyebabkan terminasi proses normal dan nilai status & 0377 dikembalikan ke induk.

Dari halaman manual abort ():

Batalkan () pertama-tama membuka blokir sinyal SIGABRT, dan kemudian menaikkan sinyal itu untuk proses panggilan. Ini menghasilkan penghentian proses yang abnormal kecuali jika sinyal SIGABRT ditangkap dan penangan sinyal tidak kembali.

Federico A. Ramponi
sumber
4

abortmengirimkan SIGABRTsinyal. aborttidak kembali ke penelepon. Penangan default untuk SIGABRTsinyal menutup aplikasi. stdioaliran file memerah, lalu ditutup. Destructors untuk instance kelas C ++ tidak, (tidak yakin yang ini - mungkin hasilnya tidak terdefinisi?).

exitmemiliki callback sendiri, diatur dengan atexit. Jika panggilan balik ditentukan (atau hanya satu), mereka dipanggil dalam urutan terbalik dari pesanan pendaftaran mereka (seperti tumpukan), kemudian program keluar. Seperti abort, exittidak kembali ke penelepon. stdioaliran file memerah, lalu ditutup. Juga, destruktor untuk instance kelas C ++ dipanggil.

strager
sumber
exit dapat memiliki beberapa fungsi callback terdaftar melalui atexit, ketika exit dipanggil semua fungsi callback akan dipanggil dalam urutan terbalik di mana mereka terdaftar.
Robert Gamble
@ Tamble, Tentu saja, saya menyebutkannya sendiri beberapa menit yang lalu dalam komentar untuk jawaban @ Bondy Saya akan mengedit jawaban saya sendiri untuk mencerminkan hal itu.
strager