ใน C และ C ++ ความแตกต่างระหว่างexit()
และabort()
อย่างไร? ฉันกำลังพยายามยุติโปรแกรมหลังจากเกิดข้อผิดพลาด (ไม่ใช่ข้อยกเว้น)
ใน C และ C ++ ความแตกต่างระหว่างexit()
และabort()
อย่างไร? ฉันกำลังพยายามยุติโปรแกรมหลังจากเกิดข้อผิดพลาด (ไม่ใช่ข้อยกเว้น)
คำตอบ:
abort()
ออกจากโปรแกรมของคุณโดยไม่เรียกใช้ฟังก์ชันที่ลงทะเบียนโดยใช้atexit()
ก่อนและไม่ต้องเรียกตัวทำลายวัตถุก่อน exit()
ทำทั้งสองอย่างก่อนออกจากโปรแกรมของคุณ มันไม่เรียกตัวทำลายสำหรับวัตถุอัตโนมัติแม้ว่า ดังนั้น
A a;
void test() {
static A b;
A c;
exit(0);
}
จะทำลายa
และb
ถูกต้อง แต่จะไม่เรียก destructors 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);
แทน
abortส่งสัญญาณ 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;
}
ความคิดเห็นที่:
หากยกเลิกเป็น uncommented: ไม่มีอะไรจะพิมพ์และ destructor ของ SomeObject จะไม่ถูกเรียกว่า
หากมีการแสดงความคิดเห็นเกี่ยวกับการยกเลิกดังข้างต้น: ผู้ทำลายวัตถุบางอย่างจะถูกเรียกคุณจะได้รับผลลัพธ์ต่อไปนี้:
ฟังก์ชันออก 2
ฟังก์ชันออก 1
สิ่งต่อไปนี้เกิดขึ้นเมื่อโปรแกรมเรียกใช้exit
():
atexit
ฟังก์ชันจะดำเนินการtmpfile
จะถูกลบออกabort
() ฟังก์ชันส่งSIGABRT
สัญญาณไปยังกระบวนการปัจจุบันถ้ามันไม่ได้ถูกจับโปรแกรมจะสิ้นสุดลงด้วยการรับประกันว่าเปิดลำธารล้าง / ปิดหรือว่าไฟล์ชั่วคราวที่สร้างขึ้นผ่านtmpfile
จะถูกลบออกatexit
ฟังก์ชั่นการลงทะเบียนจะไม่ได้เรียกว่าและไม่ใช่ สถานะการออกเป็นศูนย์จะถูกส่งกลับไปยังโฮสต์
จากหน้าคู่มือ exit ():
ฟังก์ชัน exit () ทำให้กระบวนการสิ้นสุดตามปกติและค่าสถานะ & 0377 จะถูกส่งกลับไปยังพาเรนต์
จากหน้าคู่มือการยกเลิก ():
ขั้นแรก abort () จะปลดบล็อกสัญญาณ SIGABRT จากนั้นเพิ่มสัญญาณดังกล่าวสำหรับกระบวนการโทร ส่งผลให้กระบวนการยุติผิดปกติเว้นแต่สัญญาณ SIGABRT ถูกจับได้และตัวจัดการสัญญาณไม่กลับมา
abort
ส่งSIGABRT
สัญญาณ abort
ไม่กลับไปที่ผู้โทร ตัวจัดการเริ่มต้นสำหรับSIGABRT
สัญญาณปิดแอปพลิเคชัน stdio
สตรีมไฟล์จะล้างแล้วปิด อย่างไรก็ตามตัวทำลายสำหรับอินสแตนซ์คลาส C ++ นั้นไม่เป็นเช่นนั้น (ไม่แน่ใจในอันนี้ - ผลลัพธ์อาจไม่ได้กำหนด?)
exit
มีการเรียกกลับของตัวเองตั้งค่าด้วยatexit
. หากระบุการเรียกกลับ (หรือเพียงรายการเดียว) ระบบจะเรียกตามลำดับย้อนกลับของลำดับการลงทะเบียน (เช่นสแต็ก) จากนั้นโปรแกรมจะออก เช่นเดียวกับabort
, exit
ไม่ได้กลับไปยังผู้โทร stdio
สตรีมไฟล์จะล้างแล้วปิด นอกจากนี้ยังมีการเรียกตัวทำลายสำหรับอินสแตนซ์คลาส C ++