Thứ Hai, 27 tháng 4, 2026

Memory leak là gì? Lỗi "rò rỉ bộ nhớ" – code vẫn chạy nhưng âm thầm giết chết chương trình

Trong lúc quậy code C, có thể bạn đã gặp một tình huống chương trình dường như "có chút hơi men"...lờ đờ, ngà ngà say:
  • Chương trình chạy ngon
  • Không crash
  • Không báo lỗi
👉 Nhưng chạy một lúc thì:
  • chậm dần
  • lag dần
  • rồi… "đứng hình"
Bạn nghĩ:
"Chắc máy yếu…", hoặc là "mạng yếu"
👉 Không. Rất có thể bạn vừa dính memory leak.


Memory leak là gì?

Nói đơn giản:
Memory leak xảy ra khi bạn cấp phát bộ nhớ nhưng quên giải phóng

Trong C:
int *p = malloc(sizeof(int));
👉 Bạn đã "xin" một vùng nhớ từ hệ điều hành
Nhưng nếu bạn không:
free(p);
👉 Vùng nhớ đó sẽ không bao giờ được trả lại


Ví dụ đời thường 

Bạn đi thuê phòng khách sạn trong kỳ nghỉ Lễ. Sau đó khóa cửa phòng, quay về nhà, đi làm đi học như bình thường.
Nhưng… không bao giờ trả phòng khách sạn.
👉 Một mình bạn chiếm 1 phòng → không sao
👉 1000 người như vậy → hết phòng → "toang"


Ví dụ code kinh điển
#include <stdlib.h>
int main() {
    while (1) {
        int *p = malloc(sizeof(int));
    }
}

👉 Mỗi vòng lặp:
xin thêm 1 vùng nhớ
nhưng không trả
👉 Kết quả:
  • RAM tăng dần
  • rồi… 💀

Vì sao memory leak nguy hiểm?

Khác với segmentation fault:
❌ Segfault → crash ngay (còn biết đường sửa)
❌ Memory leak → không crash ngay. Cứ tưởng là mọi thứ ổn!
👉 Nó âm thầm:
  • ăn RAM
  • làm chương trình chậm
  • lâu dài → sập
Kiểu như sóng biển vỗ bờ, âm thầm xâm lấn vậy...Từ từ, từ từ...đất lở, sụt lún lúc nào không hay...


5 nguyên nhân phổ biến 

1. Quên free
int *p = malloc(sizeof(int));
// quên free
👉 Đây là "classic"

2. Ghi đè pointer
int *p = malloc(sizeof(int));
p = malloc(sizeof(int)); // leak vùng nhớ cũ
👉 Bạn mất luôn địa chỉ vùng nhớ đầu tiên → không free được nữa

3. Return sớm (quên dọn dẹp)
int *p = malloc(sizeof(int));
if (error) return; // leak
👉 Chưa kịp free đã "bỏ chạy"

4. Cấu trúc phức tạp (struct, linked list…)

👉 Khi dùng:
list
tree
👉 Rất dễ:
free thiếu
free sai

5. Lặp nhiều lần (loop)

👉 Code tưởng đúng:
while (1) {
    char *buf = malloc(100);
}
👉 Nhưng:
chạy lâu → chết chắc

Để hiểu rõ hơn, mục sở thị kết quả bằng xương bằng thịt, chúng ta sẽ cần thực hành một chút.
Bạn copy code sau vào:
👉 Online C Compiler

#include <stdlib.h>
#include <stdio.h>
int main() {
    int count = 0;
    while (1) {
        malloc(1000); // leak
        count++;
        if (count % 10000 == 0) {
            printf("Allocated %d blocks\n", count);
        }
    }
    return 0;
}

Bấm Run chạy thử

👉 Bạn sẽ thấy:
  1. chương trình chạy
  2. nhưng RAM tăng dần

Cách phát hiện memory leak

✅ Cách 1: Quan sát RAM
Task Manager / top / htop
👉 thấy RAM tăng liên tục → nghi ngay
✅ Cách 2: Dùng tool chuyên dụng
Ví dụ:
Valgrind (Linux)
valgrind ./program
👉 Nó sẽ báo:
chỗ nào leak
leak bao nhiêu
✅ Cách 3: Tự discipline (Tự mò mẫm)
👉 Rule đơn giản:
malloc ở đâu → free ở đó (hoặc có kế hoạch rõ ràng)

Cách tránh memory leak 

✅ 1. malloc → luôn nghĩ đến free
👉 Viết code mà không nghĩ đến free là… sớm muộn gì cũng leak
✅ 2. Set NULL sau khi free
free(p);
p = NULL;
👉 Tránh dùng lại nhầm
✅ 3. Không ghi đè pointer
👉 Nếu cần:
free(p);
p = malloc(sizeof(int));
✅ 4. Với project lớn → viết rule rõ ràng
Ai cấp phát?
Ai giải phóng?
👉 Không rõ = leak
Một sự thật hơi "đau"
👉 Rất nhiều phần mềm ngoài đời:
không crash
nhưng chạy lâu → chậm
👉 Lý do: memory leak

Tổng kết
Memory leak không làm chương trình crash ngay
👉 Nhưng nó "ăn dần" tài nguyên

Chỉ cần nhớ:
  • malloc → phải free
  • Không free → leak
  • Leak nhiều → chết

FAQ

❓ Memory leak có gây segmentation fault không?
→ Không trực tiếp, nhưng có thể gián tiếp khi hết memory

❓ Có thể tránh hoàn toàn memory leak không?
→ Rất khó, nhưng có thể giảm rất nhiều nếu quản lý tốt

❓ Ngôn ngữ khác có memory leak không?
→ Có, nhưng ít hơn (do có garbage collector)