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", hoặc "một cái gì đó...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ụ thực tế 

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


Thực hành

Để 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:
  • chương trình chạy
  • 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 --> rất đáng nghi 

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, rất cầ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 nhanh

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)