Hàm malloc() trong thư viện C với EXAMPLE
⚡ Tóm tắt thông minh
Hàm malloc() trong C dành riêng một khối bộ nhớ trên heap khi chạy chương trình và trả về một con trỏ void trỏ đến byte đầu tiên của khối bộ nhớ đó, cho phép các chương trình yêu cầu vùng nhớ có kích thước chưa được biết cho đến khi mã thực sự được thực thi.
malloc trong C là gì?
Hàm malloc() là viết tắt của việc cấp phát bộ nhớ. Đây là một chức năng được sử dụng để phân bổ động một khối bộ nhớ. Nó dự trữ không gian bộ nhớ có kích thước được chỉ định và trả về con trỏ null trỏ đến vị trí bộ nhớ. Con trỏ trả về thường có kiểu void. Điều đó có nghĩa là chúng ta có thể gán hàm malloc cho bất kỳ con trỏ nào.
cú pháp
ptr = (cast_type *) malloc (byte_size);
Ở đây,
- ptr là con trỏ của cast_type.
- Hàm malloc trả về một con trỏ tới bộ nhớ được phân bổ của byte_size.
Example: ptr = (int *) malloc (50)
Khi câu lệnh này được thực thi thành công, không gian bộ nhớ 50 byte sẽ được dành riêng. Địa chỉ của byte đầu tiên của vùng dành riêng được gán cho con trỏ ptr kiểu int.
Hãy xem xét một ví dụ khác về triển khai malloc:
#include <stdlib.h> int main(){ int *ptr; ptr = malloc(15 * sizeof(*ptr)); /* a block of 15 integers */ if (ptr != NULL) { *(ptr + 5) = 480; /* assign 480 to sixth integer */ printf("Value of the 6th integer is %d",*(ptr + 5)); } }
Đầu ra:
Value of the 6th integer is 480
Lưu ý rằng sizeof(*ptr) được sử dụng thay vì sizeof(int) để làm cho mã mạnh mẽ hơn khi khai báo *ptr được ép kiểu sang một kiểu dữ liệu khác sau này.
Việc phân bổ có thể thất bại nếu bộ nhớ không đủ. Trong trường hợp này, nó trả về một con trỏ NULL. Vì vậy, bạn nên bao gồm mã để kiểm tra con trỏ NULL.
Hãy nhớ rằng vùng nhớ được cấp phát là liền kề và có thể được coi như một mảng. Chúng ta có thể sử dụng con trỏ Sử dụng phép toán số học để truy cập các phần tử mảng thay vì dùng dấu ngoặc vuông [ ]. Chúng tôi khuyên bạn nên dùng dấu + để tham chiếu đến các phần tử mảng vì việc sử dụng phép tăng ++ hoặc += sẽ thay đổi địa chỉ được lưu trữ bởi con trỏ.
Hàm Malloc cũng có thể được sử dụng với kiểu dữ liệu ký tự cũng như các kiểu dữ liệu phức tạp như cấu trúc.
Tại sao nên sử dụng malloc() trong C?
Mảng tĩnh và các biến thông thường cố định kích thước của chúng khi chương trình được biên dịch, điều này gây lãng phí không gian khi yêu cầu thực tế nhỏ hơn và dẫn đến lỗi hoàn toàn khi yêu cầu lớn hơn. Hàm malloc() giải quyết vấn đề này bằng cách yêu cầu bộ nhớ trong thời gian chạy, do đó chương trình có thể định kích thước bộ đệm chính xác bằng lượng dữ liệu mà nó nhận được. Tính linh hoạt trong thời gian chạy này là cốt lõi của malloc(). cấp phát bộ nhớ động trong C.
Cấp phát bộ nhớ động bằng hàm malloc() là lựa chọn phù hợp trong một số trường hợp phổ biến:
- Lượng dữ liệu đầu vào chưa được biết cho đến khi chương trình chạy, ví dụ như đọc một tập tin hoặc một danh sách do người dùng cung cấp.
- Cần những khối dữ liệu lớn đến mức vượt quá giới hạn của ngăn xếp, vì hàm malloc() lấy dữ liệu từ vùng nhớ heap lớn hơn nhiều.
- Dữ liệu phải tồn tại lâu hơn hàm đã tạo ra nó, bởi vì bộ nhớ heap vẫn tồn tại cho đến khi được giải phóng một cách rõ ràng.
- Cấu trúc và mảng cần phải mở rộng hoặc thu hẹp trong quá trình thực thi chương trình.
Vì khối dữ liệu dành riêng được trả về dưới dạng con trỏ, nên nó có thể được truyền giữa các hàm một cách hiệu quả mà không cần sao chép dữ liệu cơ bản.
Cách giải phóng bộ nhớ được cấp phát bởi malloc()
Vùng nhớ được cấp phát bởi hàm malloc() nằm trên heap và không bao giờ được giải phóng tự động. Khi một chương trình liên tục cấp phát mà không giải phóng, nó sẽ dần dần tiêu thụ hết bộ nhớ khả dụng, một lỗi được gọi là rò rỉ bộ nhớ. Hàm free() trả về một khối bộ nhớ đã được giải phóng cho hệ thống để không gian đó có thể được sử dụng lại.
Hàm free() nhận một đối số duy nhất, là con trỏ mà hàm malloc() trả về, và giải phóng toàn bộ khối bộ nhớ cùng một lúc:
int *ptr; ptr = malloc(10 * sizeof(int)); if (ptr != NULL) { /* use the allocated memory here */ free(ptr); /* release the block */ ptr = NULL; /* avoid a dangling pointer */ }
Hãy tuân thủ các quy tắc này để quản lý bộ nhớ động một cách an toàn:
- Hãy gọi hàm free() chính xác một lần cho mỗi lần cấp phát bộ nhớ thành công bằng hàm malloc(); việc giải phóng cùng một khối bộ nhớ hai lần sẽ gây ra hành vi không xác định.
- Hãy đặt con trỏ về NULL sau khi giải phóng để nó không thể được sử dụng lại như một con trỏ lơ lửng.
- Không bao giờ được giải phóng (free()) một con trỏ mà hàm malloc() không trả về giá trị, kể cả con trỏ được dịch chuyển bằng phép toán con trỏ.
- Hãy khớp mỗi lần cấp phát bộ nhớ với một lần giải phóng tương ứng trước khi con trỏ ra khỏi phạm vi.
Keeping Phân bổ và giải phóng bộ nhớ một cách cân bằng là nguyên tắc cốt lõi của quản lý bộ nhớ thủ công trong C, và nó ngăn ngừa cả rò rỉ bộ nhớ lẫn sự cố do việc tái sử dụng bộ nhớ đã được giải phóng gây ra.
malloc() và calloc(): Những điểm khác biệt chính
malloc() và calloc () Cả hai hàm đều dành riêng bộ nhớ heap, nhưng chúng khác nhau về các tham số và cách xử lý khối bộ nhớ mới. Hàm malloc() nhận một tham số là tổng số byte và để nội dung khối bộ nhớ chưa được khởi tạo, do đó khối bộ nhớ chứa các giá trị rác không thể dự đoán được cho đến khi chương trình ghi vào đó. Hàm calloc() nhận hai tham số là số lượng phần tử và kích thước của mỗi phần tử, và xóa toàn bộ byte về 0 trước khi trả về con trỏ.
Những khác biệt thực tế nằm ở ba điểm sau:
- Khởi tạo: calloc() xóa toàn bộ vùng nhớ về 0, trong khi malloc() thì không, điều này khiến malloc() nhanh hơn một chút khi các giá trị sẽ bị ghi đè sau đó.
- Lập luận: bạn viết malloc(n * size) nhưng calloc(n, size) để dành riêng cùng một mảng.
- Trường hợp sử dụng: chọn calloc() khi cần một khối bộ nhớ sạch, được ghi toàn số 0, và chọn malloc() khi tốc độ được ưu tiên và việc khởi tạo được thực hiện thủ công.
Cả hai hàm đều được khai báo trong stdlib.h, cả hai đều trả về con trỏ void hoặc NULL khi thất bại, và cả hai đều trả lại bộ nhớ bằng cùng một hàm free().


