Tôi muốn biết sự khác biệt giữa cấp phát bộ nhớ tĩnh và cấp phát bộ nhớ động là gì?
Bạn có thể giải thích điều này với bất kỳ ví dụ nào?
Tôi muốn biết sự khác biệt giữa cấp phát bộ nhớ tĩnh và cấp phát bộ nhớ động là gì?
Bạn có thể giải thích điều này với bất kỳ ví dụ nào?
Câu trả lời:
Có ba loại phân bổ - tĩnh, tự động và động.
Phân bổ tĩnh có nghĩa là bộ nhớ cho các biến của bạn được cấp phát khi chương trình bắt đầu. Kích thước được cố định khi chương trình được tạo. Nó áp dụng cho các biến toàn cục, biến phạm vi tệp và các biến đủ điều kiệnstatic
hàm bên trong được xác định.
Cấp phát bộ nhớ tự động xảy ra cho các biến (không tĩnh) được xác định bên trong các hàm và thường được lưu trữ trên ngăn xếp (mặc dù tiêu chuẩn C không bắt buộc phải sử dụng ngăn xếp). Bạn không phải dự trữ thêm bộ nhớ bằng cách sử dụng chúng, nhưng mặt khác, cũng có quyền kiểm soát hạn chế đối với thời gian tồn tại của bộ nhớ này. Vd: biến tự động trong một hàm chỉ ở đó cho đến khi hàm kết thúc.
void func() {
int i; /* `i` only exists during `func` */
}
Cấp phát bộ nhớ động hơi khác một chút. Bây giờ bạn kiểm soát kích thước chính xác và thời gian tồn tại của các vị trí bộ nhớ này. Nếu bạn không giải phóng nó, bạn sẽ gặp phải tình trạng rò rỉ bộ nhớ, có thể khiến ứng dụng của bạn gặp sự cố, vì tại một số thời điểm, hệ thống không thể phân bổ thêm bộ nhớ.
int* func() {
int* mem = malloc(1024);
return mem;
}
int* mem = func(); /* still accessible */
Trong ví dụ trên, bộ nhớ được cấp phát vẫn hợp lệ và có thể truy cập được, mặc dù chức năng đã kết thúc. Khi bạn làm xong bộ nhớ, bạn phải giải phóng nó:
free(mem);
Đây là một câu hỏi phỏng vấn tiêu chuẩn:
Bộ nhớ được cấp phát trong thời gian chạy bằng cách sử dụng calloc()
, malloc()
và bạn bè. Đôi khi nó còn được gọi là bộ nhớ 'heap', mặc dù nó không liên quan gì đến ref cấu trúc dữ liệu heap .
int * a = malloc(sizeof(int));
Bộ nhớ đống sẽ tồn tại cho đến khi free()
được gọi. Nói cách khác, bạn kiểm soát thời gian tồn tại của biến.
Đây là cái thường được gọi là bộ nhớ 'ngăn xếp' và được cấp phát khi bạn nhập một phạm vi mới (thường là khi một hàm mới được đẩy lên ngăn xếp cuộc gọi). Khi bạn di chuyển ra khỏi phạm vi, các giá trị của địa chỉ bộ nhớ tự động không được xác định và việc truy cập chúng là một lỗi .
int a = 43;
Lưu ý rằng phạm vi không nhất thiết có nghĩa là chức năng. Phạm vi có thể lồng trong một hàm và biến sẽ chỉ nằm trong phạm vi trong khối mà nó được khai báo. Cũng lưu ý rằng nơi bộ nhớ này được cấp phát không được chỉ định. (Bình tĩnh hệ thống nó sẽ nằm trên ngăn xếp hoặc đăng ký để tối ưu hóa)
Được cấp phát tại thời điểm biên dịch * và thời gian tồn tại của một biến trong bộ nhớ tĩnh là thời gian tồn tại của chương trình .
Trong C, bộ nhớ tĩnh có thể được cấp phát bằng cách sử dụng static
từ khóa. Phạm vi chỉ là đơn vị biên dịch.
Mọi thứ trở nên thú vị hơn khi extern
từ khóa được xem xét . Khi một extern
biến được xác định , trình biên dịch sẽ cấp phát bộ nhớ cho nó. Khi một extern
biến được khai báo , trình biên dịch yêu cầu biến đó phải được định nghĩa ở nơi khác. Không khai báo / xác định extern
biến sẽ gây ra sự cố liên kết, trong khi không khai báo / định nghĩastatic
biến sẽ gây ra vấn đề biên dịch.
trong phạm vi tệp, từ khóa tĩnh là tùy chọn (bên ngoài một hàm):
int a = 32;
Nhưng không phải trong phạm vi hàm (bên trong một hàm):
static int a = 32;
Về mặt kỹ thuật, extern
và static
là hai lớp biến riêng biệt trong C.
extern int a; /* Declaration */
int a; /* Definition */
Hơi khó hiểu khi nói rằng bộ nhớ tĩnh được cấp phát tại thời điểm biên dịch, đặc biệt nếu chúng ta bắt đầu xem xét rằng máy biên dịch và máy chủ có thể không giống nhau hoặc thậm chí có thể không trên cùng một kiến trúc.
Có thể tốt hơn khi nghĩ rằng việc cấp phát bộ nhớ tĩnh được xử lý bởi trình biên dịch hơn là cấp phát tại thời điểm biên dịch .
Ví dụ, trình biên dịch có thể tạo ra một data
phần trong tệp nhị phân đã biên dịch và khi chương trình được tải vào bộ nhớ, địa chỉ trongdata
phân đoạn của chương trình sẽ được sử dụng làm vị trí của bộ nhớ được cấp phát. Điều này có nhược điểm rõ ràng là làm cho tệp nhị phân được biên dịch rất lớn nếu sử dụng nhiều bộ nhớ tĩnh. Có thể viết một tệp nhị phân nhiều gigabyte được tạo từ ít hơn nửa tá dòng mã. Một tùy chọn khác là để trình biên dịch đưa mã khởi tạo sẽ cấp phát bộ nhớ theo một số cách khác trước khi chương trình được thực thi. Mã này sẽ thay đổi tùy theo nền tảng và hệ điều hành đích. Trong thực tế, các trình biên dịch hiện đại sử dụng heuristics để quyết định sử dụng tùy chọn nào trong số các tùy chọn này. Bạn có thể tự mình thử điều này bằng cách viết một chương trình C nhỏ phân bổ một mảng tĩnh lớn gồm các mục 10k, 1m, 10m, 100m, 1G hoặc 10G. Đối với nhiều trình biên dịch, kích thước nhị phân sẽ tiếp tục tăng tuyến tính với kích thước của mảng và vượt qua một điểm nhất định,
Lớp bộ nhớ cuối cùng là các biến 'đăng ký'. Như mong đợi, các biến thanh ghi nên được cấp phát trên thanh ghi của CPU, nhưng quyết định thực sự được để cho trình biên dịch. Bạn không thể biến một biến đăng ký thành một tham chiếu bằng cách sử dụng address-of.
register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */
Hầu hết các trình biên dịch hiện đại thông minh hơn bạn trong việc chọn biến nào nên được đưa vào thanh ghi :)
int * a = malloc(sizeof(*a));
Thay vào đó, tôi đề xuất , để tránh lặp lại loại a
. Điều này làm cho mọi thứ dễ dàng hơn nhiều nếu loại a
thay đổi.
Cấp phát bộ nhớ tĩnh: Trình biên dịch phân bổ không gian bộ nhớ cần thiết cho một biến đã khai báo. Bằng cách sử dụng địa chỉ của toán tử, địa chỉ dành riêng sẽ được lấy và địa chỉ này có thể được gán cho một biến con trỏ. cách gán giá trị con trỏ cho một biến con trỏ được gọi là cấp phát bộ nhớ tĩnh. bộ nhớ được gán trong thời gian biên dịch.
Cấp phát bộ nhớ động: Nó sử dụng các hàm như malloc () hoặc calloc () để lấy bộ nhớ động. phân bổ.memory được xác định trong thời gian chạy.
Phân bổ bộ nhớ tĩnh:
Phân bổ bộ nhớ động:
Sự khác biệt giữa PHÂN PHỐI BỘ NHỚ TRẠNG THÁI và PHÂN PHỐI BỘ NHỚ ĐỘNG
Bộ nhớ được cấp phát trước khi bắt đầu thực thi chương trình (Trong quá trình biên dịch).
Bộ nhớ được cấp phát trong quá trình thực hiện chương trình.
Không có hành động cấp phát bộ nhớ hoặc phân bổ bộ nhớ nào được thực hiện trong khi Thực thi.
Các ràng buộc bộ nhớ được thiết lập và phá hủy trong quá trình thực thi.
Các biến vẫn được phân bổ vĩnh viễn.
Chỉ được phân bổ khi đơn vị chương trình đang hoạt động.
Được triển khai bằng cách sử dụng ngăn xếp và đống.
Được triển khai bằng cách sử dụng các phân đoạn dữ liệu.
Con trỏ là cần thiết để truy cập các biến.
Không cần con trỏ được phân bổ động.
Thực thi nhanh hơn Dynamic.
Thực hiện chậm hơn tĩnh.
Cần thêm dung lượng bộ nhớ.
Yêu cầu ít dung lượng bộ nhớ hơn.
Cấp phát bộ nhớ tĩnh được cấp phát bộ nhớ trước khi chương trình pf thực thi trong thời gian biên dịch. Vị trí bộ nhớ động là bộ nhớ được định vị trong quá trình thực thi chương trình tại thời điểm chạy.