Trong lập trình C, có thể lúc này hay lúc khác bạn từng nghe qua 2 khái niệm:
- Stack
- Heap
Nghe thì rất "học thuật", rất "khoa học máy tính", rất "computer science", nhưng thực tế thì…
Phần lớn lính mới: đọc tài liệu xong, nghe thầy giảng xong vẫn.... không hiểu gì
Và nguy hiểm hơn:
Hiểu mơ hồ, đọc qua vài tài liệu nhưng vẫn "lơ mơ" --> code sai --> dính bug --> debug muốn "trầm cảm"
Stack và Heap là hai vùng bộ nhớ chính trong chương trình C.
- Stack dùng cho biến cục bộ, cấp phát tự động
- Heap dùng cho cấp phát động (malloc/free)
Hiểu rõ sự khác nhau giữa stack và heap sẽ giúp bạn tránh:
- segmentation fault
- memory leak
- bug khó hiểu
Ví dụ thực tế
Bạn tưởng tượng:
- Stack = balo đeo sau lưng
- Nhỏ gọn
- Lấy ra nhanh
- Dùng xong tự dọn
Nhưng:
- Không chứa được nhiều
- Nhét quá --> "toang" (stack overflow)
- Heap = kho chứa đồ
- Rộng rãi
- Muốn để bao nhiêu cũng được
Nhưng:
- Bạn phải tự quản lý
- Quên dọn → rác đầy (memory leak)
Tóm lại:
Stack Heap
Nhanh Chậm hơn
Tự động Tự quản lý
Nhỏ Lớn
An toàn hơn Dễ lỗi hơn
Code minh họa
Stack
int main() {
int x = 10; // nằm trên stack
}Khi hàm kết thúc:
x tự biến mất
bạn không cần làm gì
Heap
#include <stdlib.h>
int main() {
int *p = malloc(sizeof(int)); // heap
*p = 10;
free(p); // phải tự giải phóng
}Nếu bạn quên free:
--> memory leak
Sự khác nhau quan trọng nhất
1. Vòng đời (lifetime)
Stack: sống theo function
Heap: sống tới khi bạn free
Đây là nguồn gốc của rất nhiều bug
2. Tốc độ
Stack: cực nhanh
Heap: chậm hơn (do phải xin OS)
Nên:
- dùng stack nếu có thể
- chỉ dùng heap khi cần
3. Kích thước
Stack: giới hạn (~ vài MB)
Heap: lớn hơn nhiều
Nếu bạn làm:
int arr[10000000]; //
Rất dễ:
--> stack overflow
4. Mức độ "nguy hiểm"
Stack: ít lỗi hơn
Heap: rất dễ gây:
- memory leak
- segmentation fault
Những lỗi "kinh điển" liên quan stack vs heap
1. Trả về biến stack
int* foo() {
int x = 10;
return &x; //
}
x nằm trên stack → ra khỏi hàm là "bay màu"
2. Dùng heap nhưng quên free
Bạn đã gặp ở phần trước
3. Stack overflow (đệ quy vô hạn)
Gọi hàm mãi --> stack đầy --> crash
Chúng ta cần "thí nghiệm" để thấy kết quả
Bạn chạy code sau trên Online C Compiler :
#include <stdio.h>
void f() {
int arr[1000000]; // stack lớn
printf("Still running...\n");
f();
}
int main() {
f();
}Kết quả:
"hì hục" chạy vài lần
rồi sau đó… (xong phim :))
Khi nào dùng Stack, khi nào dùng Heap?
Dùng Stack khi:
- Biến nhỏ
- Dùng trong function
- Không cần tồn tại lâu
Dùng Heap khi:
- Dữ liệu lớn
- Cần tồn tại lâu
- Cần chia sẻ giữa nhiều function
Một quy tắc "sống còn"
Nếu bạn không chắc → dùng stack trước
Khi stack không đủ → mới dùng heap
Một sự thật hơi "khó nuốt" vì...đơn giản quá!
Rất nhiều bug "khó hiểu" trong C:
- segmentation fault
- memory leak
Đều bắt nguồn từ việc:
- Không hiểu rõ stack vs heap
Tổng kết
- Stack = nhanh, gọn, tự động
- Heap = linh hoạt, nhưng nguy hiểm
Hiểu được 2 cái này
Coi như bạn đã hơn 70% lính mới học C
FAQ
Stack overflow là gì?
Khi stack dùng hết bộ nhớ
Heap có bị overflow không?
Có, nhưng hiếm hơn
Ngôn ngữ khác có stack/heap không?
Có, nhưng thường được quản lý tự động
Bạn có thể cũng đang gặp: