Trong C và C ++, sự khác biệt giữa exit()
và là abort()
gì? Tôi đang cố gắng kết thúc chương trình của mình sau một lỗi (không phải là ngoại lệ).
Trong C và C ++, sự khác biệt giữa exit()
và là abort()
gì? Tôi đang cố gắng kết thúc chương trình của mình sau một lỗi (không phải là ngoại lệ).
Câu trả lời:
abort()
thoát khỏi chương trình của bạn mà không gọi các chức năng đã đăng ký bằng cách sử dụng atexit()
trước và không gọi hàm hủy của đối tượng trước. exit()
làm cả hai trước khi thoát khỏi chương trình của bạn. Nó không gọi hàm hủy cho các đối tượng tự động mặc dù. Vì thế
A a;
void test() {
static A b;
A c;
exit(0);
}
Sẽ phá hủy a
và b
đúng cách, nhưng sẽ không gọi hàm hủy của c
. abort()
sẽ không gọi kẻ hủy diệt của cả hai đối tượng. Vì điều này là không may, Tiêu chuẩn C ++ mô tả một cơ chế thay thế đảm bảo chấm dứt hợp lý:
Các đối tượng có thời lượng lưu trữ tự động đều bị hủy trong một chương trình có chức năng
main()
không chứa đối tượng tự động và thực hiện cuộc gọi đếnexit()
. Kiểm soát có thể được chuyển trực tiếp đến như vậymain()
bằng cách ném một ngoại lệ được bắt gặpmain()
.
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);
}
}
Thay vì gọi exit()
, hãy sắp xếp mã throw exit_exception(exit_code);
đó để thay thế.
hủy bỏ gửi tín hiệu SIGABRT, thoát chỉ cần đóng ứng dụng thực hiện dọn dẹp bình thường.
Bạn có thể xử lý tín hiệu hủy bỏ theo bất kỳ cách nào bạn muốn, nhưng hành vi mặc định là đóng ứng dụng cũng bằng mã lỗi.
hủy bỏ sẽ không thực hiện phá hủy đối tượng của các thành viên tĩnh và toàn cầu của bạn, nhưng thoát sẽ .
Tất nhiên mặc dù khi ứng dụng hoàn toàn đóng, hệ điều hành sẽ giải phóng mọi bộ nhớ không tham gia và các tài nguyên khác.
Trong cả hai hủy bỏ và thoát chấm dứt chương trình (giả sử bạn không ghi đè lên hành vi mặc định), mã trả về sẽ được trả lại cho quá trình cha mẹ mà bắt đầu ứng dụng của bạn.
Xem ví dụ sau:
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;
}
Bình luận:
Nếu hủy bỏ không được ghi chú: không có gì được in và hàm hủy của someobject sẽ không được gọi.
Nếu hủy bỏ được nhận xét như trên: một số hàm hủy sẽ được gọi, bạn sẽ nhận được kết quả đầu ra sau:
chức năng thoát 2
chức năng thoát 1
Những điều sau đây xảy ra khi một chương trình gọi exit
():
atexit
chức năng được thực thitmpfile
sẽ bị xóaHàm abort
() gửi SIGABRT
tín hiệu đến quy trình hiện tại, nếu không bắt được, chương trình sẽ bị chấm dứt mà không đảm bảo rằng các luồng mở được tuôn ra / đóng hoặc các tệp tạm thời được tạo qua tmpfile
bị xóa, các atexit
hàm đã đăng ký sẽ không được gọi và không trạng thái thoát không được trả lại cho máy chủ.
Từ trang hướng dẫn exit ():
Hàm exit () gây ra chấm dứt quá trình bình thường và giá trị của trạng thái & 0377 được trả về cho cha.
Từ trang hướng dẫn hủy bỏ ():
Đầu tiên hủy bỏ () bỏ chặn tín hiệu SIGABRT và sau đó tăng tín hiệu đó cho quá trình gọi. Điều này dẫn đến việc chấm dứt bất thường của quy trình trừ khi tín hiệu SIGABRT bị bắt và bộ xử lý tín hiệu không quay trở lại.
abort
gửi SIGABRT
tín hiệu. abort
không trả lại cho người gọi Trình xử lý mặc định cho SIGABRT
tín hiệu đóng ứng dụng. stdio
dòng tập tin được tuôn ra, sau đó đóng cửa. Tuy nhiên, các cấu trúc hủy cho các thể hiện của lớp C ++ không (tuy nhiên không chắc chắn về điều này - có lẽ kết quả không được xác định?).
exit
có cuộc gọi lại riêng của nó, thiết lập với atexit
. Nếu các cuộc gọi lại được chỉ định (hoặc chỉ một), chúng được gọi theo thứ tự ngược lại với thứ tự đăng ký của chúng (như ngăn xếp), sau đó chương trình thoát. Như với abort
, exit
không trở lại với người gọi. stdio
dòng tập tin được tuôn ra, sau đó đóng cửa. Ngoài ra, các hàm hủy cho các thể hiện của lớp C ++ được gọi.