Xem thêm

Bài 17: Cấp phát động bộ nhớ với malloc, calloc và realloc trong C

Huy Erick
Trong bài viết này, chúng ta sẽ tìm hiểu về cách cấp phát động bộ nhớ bằng các hàm malloc, calloc và realloc trong ngôn ngữ lập trình C. Những hàm này sẽ giúp chúng...

Trong bài viết này, chúng ta sẽ tìm hiểu về cách cấp phát động bộ nhớ bằng các hàm malloc, calloc và realloc trong ngôn ngữ lập trình C. Những hàm này sẽ giúp chúng ta cấp phát và giải phóng bộ nhớ khi làm việc với con trỏ.

Cấp phát bộ nhớ là gì? Tại sao cần cấp phát động bộ nhớ?

Khi chúng ta tạo ra một biến, trình biên dịch sẽ đưa ra một địa chỉ để lưu trữ giá trị của biến đó. Khi sử dụng biến, chúng ta có thể truy cập vào nó bằng tên biến hoặc con trỏ. Quá trình cấp phát như vậy được gọi là "cấp phát tĩnh".

Tuy nhiên, trong trường hợp chúng ta không biết trước kích thước của một mảng, cấp phát tĩnh bộ nhớ sẽ gặp phải hai vấn đề: thiếu kích thước dẫn đến việc lưu thiếu dữ liệu và thừa kích thước dẫn tới lãng phí bộ nhớ. Vì vậy, chúng ta cần sử dụng cấp phát động trong trường hợp này.

"Cấp phát động" bộ nhớ là việc cấp phát, giải phóng và thay đổi kích thước bộ nhớ một cách linh hoạt. Điều này giúp chúng ta kiểm soát việc sử dụng bộ nhớ của chương trình. Tuy nhiên, nếu không giải phóng bộ nhớ một cách đúng đắn, chương trình sẽ gặp lỗi "tràn bộ nhớ" (Memory leak). Vì vậy, chúng ta cần cẩn thận khi sử dụng cấp phát động.

Cấp phát động và cấp phát tĩnh

Cấp phát tĩnh và cấp phát động có những điểm giống và khác nhau như sau:

Cấp phát bộ nhớ tĩnh

  • Bộ nhớ được cấp phát trước khi chạy chương trình (trong quá trình biên dịch).
  • Không thể cấp phát hoặc giải phóng bộ nhớ trong quá trình chạy chương trình.
  • Chương trình chạy nhanh hơn so với cấp phát động.
  • Tốn nhiều không gian bộ nhớ hơn.

Cấp phát bộ nhớ động

  • Bộ nhớ được cấp phát trong quá trình chạy chương trình.
  • Cho phép quản lý, phân bổ hoặc giải phóng bộ nhớ trong quá trình chạy chương trình.
  • Chương trình chạy chậm hơn so với cấp phát tĩnh.
  • Tiết kiệm được không gian bộ nhớ sử dụng.

Để cấp phát bộ nhớ động cho biến con trỏ trong ngôn ngữ C, chúng ta có thể sử dụng hàm malloc() hoặc hàm calloc(). Sử dụng hàm free() để giải phóng bộ nhớ đã cấp phát khi không cần sử dụng và sử dụng realloc() để thay đổi kích thước bộ nhớ đã cấp phát trong quá trình chạy chương trình.

cap phat dong Hình ảnh minh họa về cách cấp phát động bộ nhớ

Sử dụng hàm free

Việc cấp phát bộ nhớ động trong C, dù sử dụng malloc() hay calloc(), đều không tự giải phóng bộ nhớ. Bạn cần sử dụng hàm free() để giải phóng vùng nhớ.

Cú pháp: free(ptr); (trong đó ptr là con trỏ)

Sử dụng hàm malloc

Từ "malloc" đại diện cho cụm từ "memory allocation" (dịch: cấp phát bộ nhớ). Khi khai báo kiểu malloc, các ô nhớ sẽ được giữ nguyên bộ nhớ ban đầu (chứa dữ liệu rác).

Hàm malloc được định nghĩa như sau:

  • Kiểu trả về là con trỏ void (không có giá trị), tham số truyền vào là kích thước tính bằng byte.

Ví dụ:

int *pt = malloc(10 * sizeof(int));

Trong đoạn mã trên, chúng ta cấp phát con trỏ kiểu int, với kích thước là 10 * 4 = 40 byte (vì 1 int có kích thước 4 byte). Con trỏ pt sẽ được cấp phát 40 byte tương ứng với 10 phần tử trong mảng.

Để sử dụng malloc, chúng ta nên ép kiểu con trỏ về kiểu dữ liệu mà chúng ta sử dụng, như sau:

int *ptr;

Sử dụng hàm calloc

Hàm calloc() cấp phát bộ nhớ và khởi tạo tất cả các ô nhớ có giá trị bằng 0. Do đó, hàm calloc sẽ mất thời gian thực thi lâu hơn malloc().

Hàm calloc được định nghĩa như sau:

  • Giá trị trả về là con trỏ void, tham số truyền vào là số lượng phần tử và kích thước của mỗi phần tử.

Ví dụ:

char *pt = calloc(100, sizeof(char));

hoặc

int *ptr;

Với đoạn mã trên, chúng ta cấp phát con trỏ kiểu char với 100 phần tử và mỗi phần tử có kích thước là sizeof(char).

Sử dụng hàm realloc

Hàm realloc được sử dụng khi bạn đã cấp phát động bộ nhớ nhưng cần thêm bộ nhớ để sử dụng.

Cú pháp: ptr = (int*) realloc(ptr, m * sizeof(int)); (trong đó ptr là con trỏ đã được cấp phát động và m là kích thước thêm vào tính bằng byte).

Ví dụ:

ptr = (int*) realloc(ptr, m * sizeof(int));

Trong ví dụ này, chúng ta nhập số lượng phần tử và tính tổng các phần tử đã có rồi nhập thêm số lượng phần tử khác.

Kết quả:

Nhap so luong phan tu: 3
Nhap gia tri 1: 1
Nhap gia tri 2: 2
Nhap gia tri 3: 3
Tong = 6
Them phan tu: 2
Nhap gia tri 4: 3
Nhap gia tri 5: 5
Tong moi = 14

Việc sử dụng phương pháp calloc sẽ an toàn hơn malloc trong lập trình, vì vùng nhớ cấp phát động sẽ được gán giá trị bằng 0. Tuy nhiên, việc thêm bước gán giá trị các ô nhớ bằng 0 này sẽ làm chương trình chậm hơn so với malloc do phải thực hiện thêm thao tác.

Sử dụng realloc và free một cách linh hoạt sẽ giúp chúng ta kiểm soát sự tăng giảm của bộ nhớ dễ dàng.

Nếu bạn thấy bài viết hữu ích, hãy chia sẻ và tham gia nhóm "Nghiện Lập Trình" để giao lưu và học hỏi thêm.

Original article: Bài 17: Cấp phát động bộ nhớ với malloc, calloc và realloc trong C

1