ทั้งสามฟังก์ชันใช้สำหรับจบโปรแกรมแต่มีพฤติกรรมและจุดประสงค์ต่างกัน
exit() - Normal Termination
จบโปรแกรมอย่างปกติ พร้อม Cleanup ครบถ้วน
พฤติกรรม
- เรียก
atexit()Handlers (LIFO) - Flush I/O Buffers
- ปิด Open Streams/Files
- เรียก Destructors ของ Static/Thread-local Objects (C++)
- คืน Status ให้ OS
ไวยากรณ์
#include <stdlib.h>
void exit(int status);
ตัวอย่าง
#include <stdio.h>
#include <stdlib.h>
int main() {
int x = 10;
printf("The value of x : %d\n", x);
exit(0); // Exit Code 0 = Success
printf("This won't print");
return 0;
}
abort() - Abnormal Termination
จบโปรแกรม ทันทีและผิดปกติ ไม่ทำ Cleanup ใดๆ มักสร้าง Core Dump
พฤติกรรม
- ไม่เรียก
atexit()Handlers - ไม่ Flush Buffers
- ไม่เรียก Destructors
- สร้าง Signal
SIGABRT(อาจถูก Catch ได้) - สร้าง Core Dump (ถ้าระบบอนุญาต)
ไวยากรณ์
#include <stdlib.h>
void abort(void);
ตัวอย่าง
#include <stdio.h>
#include <stdlib.h>
int main() {
int a = 15;
printf("The value of a : %d\n", a);
abort(); // จบแบบผิดปกติ
printf("This won't print");
return 0;
}
ผลลัพธ์
The value of a : 15
Aborted (core dumped)
assert() - Debug Assertion
ตรวจสอบเงื่อนไข (Condition) ในขณะ Debug ถ้าเป็นเท็จ จะเรียก abort()
พฤติกรรม
- ถ้า Expression เป็น True: ไม่ทำอะไร (No-op)
- ถ้า Expression เป็น False: พิมพ์ Error Message แล้ว
abort() - ถ้า Define
NDEBUGก่อน Include<assert.h>: ถูก Disable ทั้งหมด (Zero Overhead)
ไวยากรณ์
#include <assert.h>
void assert(int expression);
ตัวอย่าง
#include <stdio.h>
#include <assert.h>
int main() {
int a = 15;
printf("The value of a : %d\n", a);
assert(a != 15); // False -> Abort
printf("This won't print");
return 0;
}
ผลลัพธ์
The value of a : 15
Assertion failed: a != 15, file main.c, line 9
Aborted (core dumped)
ตารางเปรียบเทียบ
| คุณสมบัติ | exit() | abort() | assert() |
|---|---|---|---|
| Termination Type | Normal | Abnormal | Abnormal (ถ้า Fail) |
| Cleanup (atexit, destructors) | ✓ ใช่ | ✗ ไม่ | ✗ ไม่ (เรียก abort) |
| Core Dump | ✗ ไม่ | ✓ ใช่ (ปกติ) | ✓ ใช่ (ผ่าน abort) |
| Return Status to OS | ✓ ใช่ | ✗ (Signal) | ✗ (Signal) |
| Use Case | Normal Exit | Critical Error | Debug Checks |
| Production Code | ✓ ใช้ได้ | ✗ หลีกเลี่ยง | ✗ Disabled by NDEBUG |
เมื่อไหร่ควรใช้แต่ละตัว
exit()
- จบโปรแกรมปกติจากฟังก์ชันที่ไม่ใช่ main()
- Error Handling ที่ต้อง Cleanup
abort()
- Critical Errors ที่ไม่สามารถ Recover ได้ (Corrupted State)
- Security Violations
- หลีกเลี่ยงในโค้ดปกติ - ใช้ Exception (C++) หรือ Error Codes แทน
assert()
- ตรวจสอบ Preconditions/Postconditions/Invariants ใน Development
- Document Assumptions ในโค้ด
- ไม่ใช่ Error Handling สำหรับ Runtime Errors (User Input, File I/O, Network)
Best Practice: Assert vs Error Handling
// ดี: Assert สำหรับ Programming Errors (Bugs)
void setAge(int age) {
assert(age >= 0 && age <= 150); // Bug ถ้า violate
this->age = age;
}
// ไม่ดี: Assert สำหรับ Runtime Errors
FILE *fp = fopen("config.txt", "r");
assert(fp != NULL); // ผิด! File ไม่มีเป็น Runtime Error ไม่ใช่ Bug
// ถูกต้อง: Error Handling สำหรับ Runtime
FILE *fp = fopen("config.txt", "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open config.txt\n");
return ERROR_CODE;
}