1
Sự khác nhau giữa bộ nhớ Heap và bộ nhớ Stack trong lập trình là gì?
0
4
xuans2huy490 đã đăng:

Bộ nhớ Heap và bộ nhớ Stack bản chất đều cùng là vùng nhớ được tạo ra và lưu trữ trong RAM khi chương trình được thực thi. Sự khác biệt cơ bản nhất giữa hai loại bộ nhớ này đó là bộ nhớ Stack được dùng để lưu trữ các biến cục bộ trong hàm, tham số truyền vào hàm, địa chỉ trả về của hàm trong khi bộ nhớ Heap được dùng để lưu trữ vùng nhớ cho các biến con trỏ được cấp phát động bởi các hàm malloc - calloc - realloc (trong C) hoặc từ khóa new (trong C++, Java,...).

Ví dụ trong ngôn ngữ lập trình C++:

#include <iostream>
using namespace std;

void main(){
    int a = 3; //Dữ liệu biến a sẽ được lưu trong bộ nhớ Stack
    int *b = new int[10]; // Dữ liệu của con trỏ b sẽ được lưu trong bộ nhớ Heap
}

Ngoài ra, còn rất nhiều trọng điểm để so sánh sự khác nhau giữa bộ nhớ Heap và bộ nhớ Stack như:

Kích thước vùng nhớ

Stack:

Kích thước của bộ nhớ Stack là cố định, tùy thuộc vào từng hệ điều hành, ví dụ hệ điều hành Windows là 1 MB, hệ điều hành Linux là 8 MB (lưu ý là con số có thể khác tùy thuộc vào kiến trúc hệ điều hành của bạn).

Heap:

Kích thước của bộ nhớ Heap là không cố định, có thể tăng giảm do đó đáp ứng được nhu cầu lưu trữ dữ liệu của chương trình.

Đặc điểm vùng nhớ.

Stack:

Vùng nhớ Stack được quản lý bởi hệ điều hành, dữ liệu được lưu trong Stack sẽ tự động hủy khi hàm thực hiện xong công việc của mình.

Heap:

Vùng nhớ Heap được quản lý bởi lập trình viên (trong C hoặc C++), dữ liệu trong Heap sẽ không bị hủy khi hàm thực hiện xong, điều đó có nghĩa bạn phải tự tay hủy vùng nhớ bằng câu lệnh free (trong C), và delete hoặc delete [] (trong C++), nếu không sẽ xảy ra hiện tượng rò rỉ bộ nhớ. Ở các ngôn ngữ lập trình bậc cao như .NET, Java, ... đã có chế dọn rác tự động (Garbage Collection), bạn không cần phải tự tay hủy vùng nhớ Heap nữa.

Vấn đề lỗi xảy ra đối với vùng nhớ:

Stack:

Bởi vì bộ nhớ Stack cố định nên nếu chương trình bạn sử dụng quá nhiều bộ nhớ vượt quá khả năng lưu trữ của Stack chắc chắn sẽ xảy ra tình trạng tràn bộ nhớ Stack (Stack overflow), các trường hợp xảy ra như bạn khởi tạo quá nhiều biến cục bộ, hàm đệ quy vô hạn,...

Ví dụ về tràn bộ nhớ Stack với hàm đệ quy vô hạn:

int foo(int x){
    printf("De quy khong gioi han\n");
    return foo(x);
}

Heap:

Nếu bạn liên tục cấp phát vùng nhớ mà không giải phóng thì sẽ bị lỗi tràn vùng nhớ Heap (Heap overflow).

Nếu bạn khởi tạo một vùng nhớ quá lớn mà vùng nhớ Heap không thể lưu trữ một lần được sẽ bị lỗi khởi tạo vùng nhớ Heap thất bại.

Ví dụ trường hợp khởi tạo vùng nhớ Heap quá lớn:

int *A = (int *)malloc(18446744073709551615);

Khi nào nên sử dụng bộ nhớ Stack và bộ nhớ Heap

Khi bạn không biết chính xác cần bao nhiêu vùng nhớ là đủ để lưu trữ dữ liệu trong khi chương trình đang chạy thì dùng bộ nhớ Heap (ví dụ điển hình là cấp phát động của mảng), còn lại thì sử dụng bộ nhớ Stack.

Hoặc khi dữ liệu quá lớn vượt quá khả năng của Stack thì bạn nên dùng Heap.

đã bổ sung 3.3 năm trước bởi
xuans2huy490
2

Bạn còn thiếu, mình xin phép bổ sung thêm:

Trong các ứng dụng đa luồng chạy song song (multithreading), mỗi luồng xử lý (thread) sẽ có vùng nhớ Stack riêng của nó, trong khi tất cả các luồng cùng chia sẻ một vùng nhớ Heap. Sử dụng chung vùng nhớ Heap đồng nghĩa với việc phải đồng bồ hóa để tránh tình trạng xảy ra mâu thuẫn giữa các luồng, cho nên cấp phát vùng nhớ Heap phải cài đặt thêm một số cơ chế do đó thực hiện lâu hơn so với cấp phát vùng nhớ Stack.

Cấp phát và hủy vùng nhớ Heap liên tục có thể xảy ra tình trạng phân mảnh bộ nhớ, từ phân mảnh bộ nhớ có thể dẫn đến lỗi cấp phát bộ nhớ thất bại như bạn đã mô tả ở trên.

V.I.P 08.08.2018
thêm bình luận...
Bạn đang thắc mắc? Ghi câu hỏi của bạn và đăng ở chế độ cộng đồng (?)