Quản lý bộ nhớ trong C

Chương này sẽ giải thích về cách quản lý bộ nhớ động trong ngôn ngữ C. Ngôn ngữ lập trình C cung cấp vài hàm khác nhau cho việc cấp phát và quản lý bộ nhớ. Những hàm này có thể tìm thấy trong Header file là <stdlib.h>.

void *calloc(int tongkichco, int kichco);

Hàm này cấp phát một mảng các phần tử có tổng kích thước là tongkichco mà kích cỡ của mỗi phần tử được tính bằng byte sẽ là kichco.

void free(void *diachi);

Hàm này giải phóng một khối bộ nhớ được xác định bởi diachi.

void *malloc(int tongkichco);

Hàm này cấp phát bộ nhớ động với kích thước tongkichco.

void *realloc(void *diachi, int kichco_moi);

Hàm này để thay đổi kích cỡ bộ nhớ đã cấp phát thành kích cỡ mới kichco_moi.

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

Khi bạn lập trình, bạn phải nhận thức về độ lớn của một mảng, sau đó nó là dễ dàng cho việc định nghĩa mảng. Ví dụ, bạn lưu trữ một tên của người bất kỳ nào, nó có thể lên tới tối đa 100 ký tự vì thế bạn có thể định nghĩa như sau:

char ten_mang[100];

Bây giờ hãy xem xét trường hợp bạn không có một ý tưởng nào về độ lớn của mảng bạn dự định lưu trữ, ví dụ bạn muốn lưu trữ một miêu tả chi tiết về một chủ đề. Tại đây bạn cần định nghĩa một con trỏ tới ký tự mà không định nghĩa bao nhiêu bộ nhớ được yêu cầu và sau đó dựa vào yêu cầu chúng ta sẽ cấp phát bộ nhớ như ví dụ dưới đây:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
   char tennhanvien[100];
   char *mieuta;

   strcpy(tennhanvien, "Tran Minh Chinh");

   /* Cap phat bo nho dong */
   mieuta = (char *) malloc(200);
   if( mieuta == NULL )
   {
      fprintf(stderr, "Error - khong the cap phat bo nho theo yeu cau\n");
   }
   else
   {
      strcpy( mieuta, "Chinh la nhan vien IT co nang luc chem gio tot!!!");
   }
   printf("Ten nhan vien la: %s\n", tennhanvien );
   printf("Mieu ta: %s\n", mieuta );
   
   printf("\n===========================\n");
   printf("QTM chuc cac ban hoc tot! \n");
}

Biên dịch và chạy chương trình C trên để xem kết quả:

Chương trình như trên có thể được viết bởi sử dụng calloc(), thay cho malloc như sau:

mieuta = (char*)calloc(200, sizeof(char));

Như thế là bạn đã hoàn toàn điều khiển việc cấp phát bộ nhớ và bạn có thể truyền bất cứ giá trị kích cỡ nào trong khi cấp phát bộ nhớ, không giống như mảng có độ dài cố định không thể thay đổi được.

Thay đổi và giải phóng bộ nhớ trong C

Khi chương trình của bạn kết thúc, hệ điều hành sẽ tự động giải phóng bộ nhớ cấp phát cho chương trình, nhưng trong thực tế khi bạn không cần bộ nhớ nữa, bạn nên giải phóng bộ nhớ bằng cách sử dụng hàm free().

Một cách khác, bạn có thể tăng hoặc giảm cỡ của khối bộ nhớ đã cấp phát bằng cách gọi hàm realloc(). Hãy kiểm tra chương trình trên lại một lần và sử dụng hàm realloc()free():

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
   char tennhanvien[100];
   char *mieuta;

   strcpy(tennhanvien, "Tran Minh Chinh");

   /* Cap phat bo nho dong */
   mieuta = (char *) malloc(100);
   if( mieuta == NULL )
   {
      fprintf(stderr, "Error - khong the cap phat bo nho theo yeu cau\n");
   }
   else
   {
      strcpy( mieuta, "Chinh la nhan vien IT co nang luc chem gio tot!!!");
   }
   /* Gia su ban muon luu tru mot mieuta nho hon */
   mieuta = (char*)calloc(50, sizeof(char));
   if( mieuta == NULL )
   {
      fprintf(stderr, "Error - khong the cap phat bo nho theo yeu cau\n");
   }
   else
   {
      strcat( mieuta, "Anh ta rat gioi!!!");
   }
   
   printf("Ten nhan vien: %s\n", tennhanvien );
   printf("Mieu ta: %s\n", mieuta );

   /* giai phong bo nho voi ham free() */
   free(mieuta);
   
   printf("\n===========================\n");
   printf("QTM chuc cac ban hoc tot! \n");
}

Biên dịch và chạy chương trình C trên để xem kết quả:

Bạn có thể thử ví dụ trên mà không sử dụng việc cấp phát thêm và hàm strcat() sẽ thông báo lỗi do không đủ bộ nhớ cấp phát.

Địa chỉ bộ nhớ trong C

Khi một biến được tạo trong C, một địa chỉ bộ nhớ sẽ được gắn với biến. Hiểu đơn giản, địa chỉ bộ nhớ là vị trí lưu biến trên máy tính.

Khi gắn một giá trị với biến, nó nằm trong địa chỉ bộ nhớ. Để truy cập nó, dùng toán tử tham chiếu (&). Kết quả đại diện cho vị trí lưu biến. Ví dụ:

int myAge = 43;
printf("%p", &myAge); // Outputs 0x7ffe5367e044

Lưu ý: Địa chỉ bộ nhớ ở dạng thập lục phân (0x…). Bạn có thể không nhận được cùng kết quả trong chương trình này.

Bạn cũng nên lưu ý rằng &myAge thường được gọi là pointer. Về cơ bản, một pointer lưu địa chỉ bộ nhớ của biến dưới dạng giá trị của nó. Để in giá trị pointer, bạn cần dùng phần tử xác định định dạng %p.

Tại sao bạn cần hiểu rõ về địa chỉ bộ nhớ?

Pointer hay con trỏ trong C rất quan trọng vì chúng cho bạn khả năng chỉnh sửa dữ liệu trong bộ nhớ máy tính - điều này có thể giảm code và cải thiện hiệu quả hoạt động.

Con trỏ là một trong số những điều khiến C trở nên nổi bật hơn những ngôn ngữ lập trình khác như Python, Java.

Bài trước: Tham số biến trong C

Bài tiếp: Tham số dòng lệnh trong C

Thứ Năm, 05/01/2023 16:46
32 👨 1.098
0 Bình luận
Sắp xếp theo
    ❖ Lập trình C