C không có cơ chế xử lý ngoại lệ (exception) built-in như C++ hay Java. Thay vào đó, C sử dụng các quy ước và hàm thư viện để báo lỗi.
Cơ chế errno
errno là biến toàn cục (thread-local trong C11) được thiết lập bởi các hàm thư viện khi xảy ra lỗi. Header: <errno.h>.
Một số mã lỗi phổ biến
| Mã | Hằng số | Mô tả |
| 2 | ENOENT | Không tìm thấy file/thư mục |
| 5 | EIO | Lỗi I/O |
| 7 | E2BIG | Danh sách đối số quá dài |
| 12 | ENOMEM | Hết bộ nhớ |
| 13 | EACCES | Truy cập bị từ chối |
| 22 | EINVAL | Đối số không hợp lệ |
Các phương pháp xử lý lỗi
1. perror() - In thông báo lỗi
#include <stdio.h>
FILE* f = fopen("nonexistent.txt", "r");
if (!f) {
perror("Mở file thất bại");
// Output: "Mở file thất bại: No such file or directory"
}
2. strerror() - Lấy chuỗi mô tả lỗi
#include <string.h>
#include <errno.h>
if (!f) {
fprintf(stderr, "Lỗi: %s\n", strerror(errno));
}
3. Trạng thái thoát (Exit status)
#include <stdlib.h>
exit(EXIT_SUCCESS); // 0 - thành công
exit(EXIT_FAILURE); // 1 - thất bại
4. Kiểm tra chia cho 0 (phòng tránh)
if (divisor == 0) {
fprintf(stderr, "Lỗi: Chia cho 0!\n");
exit(EXIT_FAILURE);
}
result = dividend / divisor;
Ví dụ hoàn chỉnh
#include <stdio.h>
#include <stdlib.h>
int main() {
int a = 28, b = 0, result;
if (b == 0) {
fprintf(stderr, "Lỗi: Chia cho 0!\n");
exit(EXIT_FAILURE);
}
result = a / b;
printf("Kết quả: %d\n", result);
exit(EXIT_SUCCESS);
}
Kết quả (với b = 0)
Lỗi: Chia cho 0!
Thực hành tốt (Best Practices)
- Luôn kiểm tra giá trị trả về của hàm (NULL, -1, EOF...)
- Kiểm tra
errno ngay sau lời gọi hàm có thể lỗi
- Dùng
stderr cho thông báo lỗi
- Trả về mã lỗi có ý nghĩa từ hàm tự viết
- Tài liệu hóa các mã lỗi có thể xảy ra