Trong vô số thứ gây...nhức đầu thì Segmentation fault là một trong những lỗi phổ biến nhất trong C/C++, thường xảy ra khi chương trình truy cập sai vùng nhớ (pointer, array, malloc...).
Thảo luận này sẽ giúp bạn hiểu nhanh nguyên nhân và cách fix.
Nếu bạn từng code C, đã viết tới "en nờ" dòng code và thấy chương trình chạy ngon lành. Chắc chắn bạn sẽ rất tự tin.
Một sáng tinh mơ, cái đầu thông thái của bạn chợt "nảy thêm một ý tưởng vĩ đại", bạn vội vàng bật máy lên, tiếp tục thêm vào những dòng code n+1, n+10...Sau đó phấn khởi bấm Run và chạy thử, hân hoan coi thử thành quả...nhưng tự nhiên "đùng" một phát chương trình tắt, không báo lỗi rõ ràng…
Chúc mừng, bạn vừa gặp segmentation fault.
Nghe có vẻ đáng sợ, nhưng thật ra nó không "ma mị" như tên gọi. Hiểu đúng thì sửa lỗi rất nhanh.
Segmentation fault là gì?
Nói đơn giản:
Segmentation fault xảy ra khi chương trình truy cập vào vùng nhớ không hợp lệ
Ví dụ đời thường dễ hiểu:
- Bạn có chìa khóa phòng A
- Nhưng lại cố mở phòng B
- Hệ điều hành: "Không được phép!" --> và thế là...crash
Dấu hiệu nhận biết
Chương trình tự tắt
Terminal báo:
Segmentation fault (core dumped) hoặc thay vì báo Program finished with exit code 0, sẽ báo một code khác 0.
Để có thể "nhìn thấy" dấu hiệu, bạn hãy chạy thử những code sau trên Online C Compiler
Sau khi bấm Run, bạn sẽ thấy Terminal báo:
Program finished with exit code 139
Press ENTER to exit console.
Thông thường trên Linux, segmentation fault sẽ trả về exit code 139.
7 nguyên nhân phổ biến
(Nếu đã được "em" segmentation fault ghé thăm thì 99% bạn sẽ dính ít nhất 1 cái)
1. Dùng con trỏ NULL
int *p = NULL;
*p = 10; // crashBạn đang ghi dữ liệu vào… "hư không"
2. Truy cập vượt mảng
int arr[3] = {1,2,3};
printf("%d", arr[10]); // crashMảng có 3 phần tử, bạn đọc phần tử thứ 11
3. Quên cấp phát bộ nhớ (malloc)
int *p;
*p = 5; // crashBạn chưa thuê nhà, nhưng đã xách vali tới ở… và "xui" cho bạn hệ điều hành là chủ nhà
4. Dùng bộ nhớ sau khi free
int *p = malloc(sizeof(int));
free(p);
*p = 10; // crashBạn đã trả phòng nhưng vẫn quay lại ở
5. Stack overflow (đệ quy vô hạn)
void f() {
f();
}Gọi chính nó mãi --> tràn stack --> crash
6. Sai kiểu con trỏ
int x = 10;
char *p = (char*)&x;
printf("%s", p); // nguy hiểmĐọc sai kiểu --> dữ liệu rác --> crash
7. Truy cập bộ nhớ không thuộc quyền
Ví dụ:
- Ghi vào vùng read-only
- Truy cập memory của process khác
Hệ điều hành sẽ chặn ngay
Debug theo kiểu dev "xịn sò"
Cách 1: In log (cách "thủ công" nhưng hiệu quả)
printf("Đến bước 1\n");
printf("Đến bước 2\n");Xem chương trình chết ở đâu
Ví dụ bạn sửa lại dòng code bên trên như sau:
#include <stdio.h>
int main() {
char *str = "Hello World"; // Pointer to read-only memory
printf("Đến bước 1\n");
str[0] = 'h'; // CRASH: Writing to read-only data
printf("Đến bước 2\n");
return 0;
}Chạy thử trên Online C Compiler
Kết quả bạn sẽ thấy chương trình chỉ in dòng chữ "Đến bước 1". Điều đó cho thấy chương trình bị lỗi ở dòng code tiếp theo "str[0] = 'h'; "
Cách 2: Dùng gdb (chuẩn dev xịn sò)
gdb ./program
runSau đó:
backtraceNó sẽ chỉ ra dòng gây lỗi
Cách 3: Compile với flag debug
gcc -g main.c -o mainCách tránh segmentation fault (dành cho lính mới)
- Luôn kiểm tra NULL
- Không truy cập vượt mảng
- malloc → nhớ free
- Không dùng pointer bừa bãi
- Debug từng bước
Một sự thật...biết rồi, khổ lắm, nói mãi!
Có khoảng 90% lỗi segmentation fault đến từ:
- pointer
- memory
Nếu bạn thấy khó hiểu, đừng lo, bạn không cô đơn đây là vấn đề thật sự rất...khó hiểu!!
Tổng kết
Segmentation fault không phải lỗi "khó"
Nó chỉ là dấu hiệu bạn đang đụng sai vùng nhớ
Hiểu được:
- pointer
- memory
Bạn sẽ xử lý được hầu hết các trường hợp
FAQ nhanh
Segmentation fault có phải lúc nào cũng do pointer không?
Không. Nhưng 80–90% liên quan đến pointer hoặc memory.
Có thể tránh hoàn toàn segmentation fault không?
Gần như không, nhưng bạn có thể giảm rất nhiều nếu quản lý memory tốt.
Vì sao code hôm qua chạy được, hôm nay lại segmentation fault?
Thường do thay đổi nhỏ trong memory, pointer hoặc dữ liệu đầu vào.
Bạn có thể cũng đang gặp:
Con trỏ NULL trong C là gì?
Memory leak nguy hiểm thế nào?
Stack vs Heap khác nhau ra sao?
Con trỏ NULL trong C là gì?
Memory leak nguy hiểm thế nào?
Stack vs Heap khác nhau ra sao?