Kỹ thuật cấp phát bộ nhớ động được sử dụng trong các hệ thống nhúng dựa trên Hệ điều hành (HĐH). Hệ điều hành chứa một (Đơn vị quản lý bộ nhớ) và nó chịu trách nhiệm xử lý các hoạt động liên quan đến cấp phát bộ nhớ. Đơn vị quản lý bộ nhớ phân bổ bộ nhớ để giữ mã cho ứng dụng và các biến liên quan đến ứng dụng. Khung nhìn khái niệm về lưu trữ của một ứng dụng và các biến liên quan đến ứng dụng được trình bày trong Hình 8.
Hình 8. Phân bổ bộ nhớ tĩnh và động
Hàm malloc (): malloc () phân bổ động một khối bộ nhớ. Hàm malloc () dự trữ một khối bộ nhớ có kích thước được chỉ định làm tham số cho hàm, trong bộ nhớ heap và trả về một con trỏ có kiểu void. Điều này có thể được gán cho một con trỏ của bất kỳ loại hợp lệ. Hình thức chung của việc sử dụng hàm malloc () được đưa ra dưới đây.
pointer = (pointer_type *) malloc (no. of bytes);
221
trong đó ‘pointer’ là một con trỏ kiểu ‘pointer_type’. ‘pointer_type’ có thể là hàm int, char, float, v.v. Hàm malloc () trả về một con trỏ kiểu ‘pointer_type’ cho một khối bộ nhớ có kích thước không. của byte. Một ví dụ điển hình được đưa ra dưới đây:
ptr= (char *) malloc(50);
Hướng dẫn này phân bổ 50 byte (Nếu có 50 byte bộ nhớ khả dụng trong vùng heap) và địa chỉ của byte đầu tiên của bộ nhớ được phân bổ trong vùng heap được gán cho con trỏ ptr của kiểu char.
Cần lưu ý rằng hàm malloc () chỉ phân bổ số byte được yêu cầu và nó sẽ không phân bổ bộ nhớ tự động cho các đơn vị của con trỏ đang sử dụng. Ví dụ: nếu lập trình viên muốn cấp phát bộ nhớ cho 100 số nguyên một cách linh hoạt, mã sau đây:
x= (int *) malloc(100);
sẽ không phân bổ kích thước bộ nhớ cho 100 số nguyên, thay vào đó, nó phân bổ bộ nhớ cho chỉ 100 byte. Để làm cho nó dự trữ bộ nhớ cho 100 biến số nguyên, mã phải được viết lại thành:
x= (int *) malloc(100 * sizeof (int));
Hàm malloc () cũng có thể được sử dụng để phân bổ bộ nhớ cho các loại dữ liệu phức tạp như con trỏ cấu trúc ngoài các loại dữ liệu thông thường như int, char, float, v.v. malloc () phân bổ các byte bộ nhớ được yêu cầu theo kiểu liên tục và việc phân bổ thất bại nếu không có đủ bộ nhớ khả dụng theo kiểu liên tục cho số byte được yêu cầu bởi các hàm malloc (). Giá trị trả về của malloc () sẽ là NULL (0) nếu thất bại. Do đó, giá trị trả về của malloc () phải được kiểm tra để đảm bảo việc cấp phát bộ nhớ có thành công hay không trước khi sử dụng con trỏ được trả về bởi hàm malloc ().
int * ptr;
if ((ptr= (int *) malloc(50 * sizeof (int)))) printf (“Memory allocated successfully”);
else
printf (“Memory allocation failed”);
malloc () chỉ phân bổ các byte bộ nhớ cần thiết và sẽ không khởi tạo bộ nhớ được phân bổ. Bộ nhớ được phân bổ chứa dữ liệu ngẫu nhiên.
calloc (): Hàm thư viện calloc () phân bổ nhiều khối byte lưu trữ và khởi tạo mỗi byte được phân bổ thành 0. Cú pháp của hàm calloc () được minh họa bên dưới.
pointer = (pointer_type *) calloc (n, size of block);
222
trong đó con trỏ là một con trỏ kiểu ‘pointer_type’. ‘pointer_type’ có thể là int, char, float, v.v ...
là viết tắt của số khối được phân bổ và kích thước của khối cho biết kích thước của byte được yêu cầu cho mỗi khối. Hàm calloc (n, kích thước của khối) phân bổ bộ nhớ liên tục cho n số khối với kích thước số byte của mỗi khối và trả về một con trỏ kiểu ‘pointer_type’ trỏ đến byte đầu tiên của khối bộ nhớ được phân bổ. Một ví dụ điển hình được đưa ra dưới đây.
ptr= (char *) calloc (50,1);
Hướng dẫn trên phân bổ 50 khối bộ nhớ liền kề mỗi kích thước một byte trong bộ nhớ heap và gán địa chỉ của byte đầu tiên của vùng bộ nhớ được phân bổ cho con trỏ ký tự ptr. Vì malloc () chỉ có khả năng phân bổ số byte cố định trong vùng heap bất kể loại lưu trữ, nên calloc () có thể được sử dụng để vượt quá giới hạn này như được thảo luận dưới đây:
ptr= (int *) calloc(50,sizeof(int));
Các tính năng được cung cấp bởi calloc () có thể được triển khai bằng hàm malloc () như:
pointer = (pointer_type *) malloc (n * size of block);
memset (pointer, 0, n * size of block);
Ví dụ:
ptr= (int *) malloc (10 * sizeof (int));
memset(ptr, 0, n * size of block);
free (): Hàm thư viện quản lý bộ nhớ C free () được sử dụng để giải phóng hoặc phân bổ bộ nhớ được phân bổ trong bộ nhớ heap bởi các hàm malloc () hoặc calloc (). Nếu bộ nhớ được cấp phát động, lập trình viên sẽ giải phóng nó nếu bộ nhớ được cấp phát động không còn cần thiết cho bất kỳ hoạt động nào. Giải phóng bộ nhớ được phân bổ động làm cho nó sẵn sàng để sử dụng cho các phân bổ động khác. Cú pháp của hàm free () được đưa ra dưới đây.
free (ptr);
ptr là con trỏ hợp lệ được trả về bởi hàm calloc () hoặc malloc () trên cấp phát bộ nhớ động. Việc sử dụng một con trỏ không hợp lệ với hàm free () có thể dẫn đến hành vi không mong muốn của ứng dụng.
Hàm realloc (): realloc () được sử dụng để thay đổi kích thước của các byte được phân bổ trong một khối bộ nhớ được cấp phát động. Bạn có thể gặp các tình huống trong đó bộ nhớ được phân bổ không đủ để chứa dữ liệu cần thiết hoặc nó dư thừa về các byte bộ nhớ được phân bổ. Cả hai tình huống này đều được xử lý bằng hàm realloc (). Hàm realloc () thay đổi kích thước của khối bộ nhớ được trỏ đến, bởi tham số con trỏ thành số byte được chỉ định bởi tham số kích thước đã sửa đổi và nó trả về một con trỏ mới cho khối. Con trỏ được chỉ định bởi tham số con trỏ phải
223
được tạo bằng các chương trình con malloc, calloc hoặc realloc và không được phân bổ với các chương trình con miễn phí hoặc realloc. Hàm realloc () có thể thay đổi vị trí của khối đã được phân bổ tùy thuộc vào kích thước mới, với việc giữ nguyên nội dung của khối đã được phân bổ và trả về một con trỏ trỏ đến byte đầu tiên của khối bộ nhớ được phân bổ lại. realloc () trả về một con trỏ void nếu có đủ bộ nhớ để cấp phát, nếu không thì trả về một con trỏ NULL.
realloc (pointer, modifi ed size);
Ví dụ:
char *p; p= (char*) malloc (10); //Allocate 10 bytes of memory p= realloc(p,15); //Change the allocation to 15 bytes realloc(p,0) is same as free(p), provided ‘p’ is a valid pointer.