- vừa được xem lúc

Memory leak trong C

0 0 3

Người đăng: Nguyễn Đặng Triều

Theo Viblo Asia

I. 📝Memory leak là gì ?

  • Điều này xảy ra khi ta dùng cấp phát động malloc(). Khi cấp phát động thì vùng nhớ đó sẽ được lưu trữ trong heap. Nếu quên free() thì vùng nhớ đó sẽ tồn tại mãi trong khi chương trình chạy (lưu ý vùng nhớ này không được sử dụng nữa). Đó gọi là memory leak. (hay rò rĩ bộ nhớ).
  • Memory leak sẽ làm giảm hiệu suất hệ thống bằng cách làm giảm dung lượng heap.

Lý thuyết chỉ đơn giản như thế thôi 😆.

II. Ví dụ

1. Vấn đề 1

Mình sẽ đưa ra một trường hợp xảy ra memory leak mà đã gặp trong dự án cá nhân.

#include <stdio.h>
#include <stdlib.h> typedef struct Student { int mssv; int age;
} Student_t; typedef struct ListStudent { int number; // só lương học sinh int current; // số lượng hộc sinh hiện tại Student_t* Students; // mảng quản lí các học sinh
} List_t; List_t* List_Init(int number) { List_t* newList = (List_t *)malloc(sizeof(List_t)); newList->number = number; newList->current = 0; newList->Students = (Student_t *)malloc(sizeof(Student_t) * number); return newList;
} Student_t* Student_Init(int mssv, int age) { Student_t* newStudent = (Student_t *)malloc(sizeof(Student_t)); newStudent->mssv = mssv; newStudent->age = age; return newStudent;
} void List_Add(List_t* list, Student_t* student) { list->Students[list->current] = *student; list->current++;
} int main()
{ List_t *list_p = List_Init(2); Student_t* A = Student_Init(1, 20); Student_t* B = Student_Init(2, 20); List_Add(list_p, A); List_Add(list_p, B); printf("So luong sinh vien: %d\n", list_p->current);
}

Output

So luong sinh vien: 2

Nếu bạn xem ví dụ này, thì hãy suy nghĩ 1 tý thử vấn đề nằm ở đâu nhé.

Nói sơ qua, ở đây mk cấp phát 2 vùng nhớ bằng 2 hàm là List_Init()Student_Init().

  • Trong List_Init() lại cấp phát tiếp 1 mảng để lưu trữ các học sinh.
  • Tổng cộng là có 3 vị trí dùng malloc.
Vậy memory leak xảy ra ở đâu ❓

Xảy ra trong hàm Student_Init().

image.png

Khi hàm List_Add được thực thi thì dữ liệu trong vùng nhớ AB được copy vào vùng nhớ do Students (member của list) quản lí. Lúc này dữ liệu đã có trong mảng Students nhưng 2 vùng nhớ AB vẫn còn tồn tại mặc dù đã hoàn thành nhiệm. Điều này sẽ gây ra 2 vùng nhớ bị chiếm dụng nhưng không được sử dụng.

Để biết vì sao List_Add copy mà không phải trỏ đến vùng nhớ AB, hãy đọc bài viết: Cấp phát bộ nhớ trong struct

Hướng giải quyết
  • Phương án 1: Sử dụng free() để có thể giải phóng hai vùng nhớ này sau khi thực hiện xong quá trình thêm vào mảng.
  • Phương án 2: Tạo đối tượng cố định trong hàm Student_Init() không sử dụng malloc() thì không cần lo về memory leak.
Student_t Student_Init(int mssv, int age) { Student_t newStudent; newStudent.mssv = mssv; newStudent.age = age; return newStudent;
} void List_Add(List_t* list, Student_t student) { list->Students[list->current] = student; list->current++;
}

Khi tạo một đối tượng trong hàm Student_Init() thì nó được xem như là một biến local được lưu trữ trên stack. Sau khi thực hiện xong nhiệm vụ, hệ điều hành sẽ tự giải phóng vùng nhớ nằm trên stack.

  • Phương án 3: Dùng mảng các con trỏ
typedef struct ListStudent { int number; // số lương học sinh int current; // số lượng hộc sinh hiện tại Student_t** Students; // mảng các con trỏ quản lí học sinh
} List_t; List_t* List_Init(int number) { List_t* newList = (List_t *)malloc(sizeof(List_t)); newList->number = number; newList->current = 0; newList->Students = (Student_t **)malloc(sizeof(Student_t*) * number); return newList;
} void List_Add(List_t* list, Student_t* student) { list->Students[list->current] = student; list->current++;
}

Mỗi con trỏ trong mảng sẽ trỏ tới vùng nhớ AB thay vì copy.

III. Tham khảo

Bình luận

Bài viết tương tự

- vừa được xem lúc

Memory layout của một chương trình C/C++

1. Đặt Vấn Đề.

0 0 58

- vừa được xem lúc

Sự khác nhau giữa bộ nhớ Heap và bộ nhớ Stack trong lập trình

1. Giới thiệu. . Như chúng ta đã biết thì việc Quản lý bộ nhớ đối với một lập trình viên là rất quan trọng.

0 0 72

- vừa được xem lúc

Tích hợp thư viện C/C++ vào một dự án Flutter như thế nào?

Chào các bạn hôm nay rảnh rỗi thì mình viết một bài hướng dẫn về cách tích hợp một thư viện C/C++ vào một dự án Flutter. Thì cũng khá đơn giãn thôi vì Flutter đã cũng cấp cho chúng ta một thư viện khá

0 0 76

- vừa được xem lúc

Programming

Definition of Programming. .

0 0 50

- vừa được xem lúc

Gọi hàm của C++ trong Python bằng ctypes

Nếu đã từng dùng qua các thư viện liên quan đến toán học của Python như numpy, các bạn sẽ để ý thấy các nó có tốc độ xử lý rất nhanh. Điều này là do một phần của package này được viết bằng C/C++ và ph

0 0 51

- vừa được xem lúc

Build ứng dụng Cross Platform với Go và CGO

1. Giới thiệu.

0 0 52