Vùng nhớ Stack trong C?

Mình thấy ít người quan tâm và không biết vùng nhớ stack này thì phải, mọi người vào thảo luận về vùng nhớ này đi :slight_smile:

5 Likes

Theo các bạn thì hai đoạn code dưới đây ngoài cú pháp thì có điểm gì khác nhau:

int arrays[100];

và

int * arrays = (int *)malloc(100 * sizeof(int));

Hậu quả của việc thực thi chương trình dưới đây là gì:

void circle()
{
	circle();
}

void main()
{
	circle();
}
4 Likes

Vùng nhớ dưới đây được tạo ra trong stack, vì vùng nhớ này sẽ được hủy khi ra khỏi scope của nó

int arrays[100];

Vùng nhớ dưới đây được tạo ra trong heap, vì vùng nhớ này sẽ không được hủy khi ra khỏi scope của nó. Có khả năng gây ra memory leak

int * arrays = (int *)malloc(100 * sizeof(int));

Hậu quả của việc thực thi chương trình dưới đây là gì:

void circle()
{
	circle();
}

void main()
{
	circle();
}
5 Likes

Stack : int arrays[100];
Stack là một phần bộ nhớ đặc biệt được quản lý một cách tự động bởi CPU theo cơ chế FILO(First In, Last Out) Cái này có thể giải thích như là bạn đưa viên bi vào 1 cái lọ vậy, viên nào vào trước thì sẽ lấy ra sau cùng.
Stack dùng để chứa các biến tạm trong quá trình thực hiện các funtion. Mỗi khi ta khai báo một biến trong hàm thì biến đó được đẩy vào stack và sau khi hàm return tất các biến tạm của hàm đó bị xóa vĩnh viễn.
Stack chứa các biến automatic (biến local) hoặc chứa các đối số khi gọi function
Bạn nào chơi game LOL chắc cũng biết stack khi dùng gươm hội kín hay sách chiêu hồn nhỉ =))

Cấp phát theo kiểu này là Heap. int * arrays = (int *)malloc(100 * sizeof(int));

Nếu heap được cấp phát mà không giải phóng thì phần bộ nhớ đó sẽ không sử dụng được và có thể dẫn đến memory leak( thiếu bộ nhớ). Heap có thể được truy cập bởi bất cứ tiến trình nào. Tốc độ truy cập Heap thấp hơn Stack

4 Likes

Stack còn chứa cả function address lúc gọi hàm nữa đó là lý do vì sao chương trình gọi hàm circle() bị stack overflow.
Thực ra tốc độ truy cập giữa Heap và Stack không khác biệt nhau là mấy, tuy nhiên do stack là vùng nhớ đã được cấp phát sẵn lúc đầu chạy chương trình và luôn cố định nên việc cấp phát và hủy rất nhanh chóng chỉ cần tăng hoặc giảm stack pointer, còn đối với vùng nhớ Heap thì việc cấp phát sẽ diễn ra lúc gọi hàm cấp phát và hủy sau khi dùng xong để tránh leak nên việc cấp phát (allocation) trên Heap chậm hơn trên stack

5 Likes

Câu hỏi này hay, nhớ hiểu cho kỹ mai mốt đi phỏng vấn chém cái này đảm bảo đậu.


chỉ dành cho sinh viên mới tốt nghiệp

1 Like

Đúng là để ý cái callstack thì đúng là vậy :smiley: Và khi dùng đệ quy mà ko kiểm soát được thì dễ bị memory leak

1 Like

trc đây mỗi ngày đánh 1 trận thế mà vẫn là kim cương đoàn 2. chúa nhật thì 2 trận. nhưng sau hơn 1 năm nay thì bỏ vì ko có time :smile:
malloc là khai báo tạm thời cho con trỏ. và con trỏ xài xong thì vứt mà :smile:
nóiđến heap nhớ đến bộ nhớ tĩnh và động . heap thuộc bộ nhớ động còn con trỏ thuộc stack ở bộ nhớ tĩnh :smile: chẳng biết có đúng ko nữa

2 Likes

cho mình hỏi nếu trong một HÀM mà mình sử dụng KIỂU CON TRỎ thì kiểu con trỏ đó được định nghĩa stack hay là heap mem vậy các bạn?

int p[10];
int foo(int x) {
 static int q [10] ;
 int r [10] ;
 int s = new int [10] ;
 switch ( x ) {
 case 1 : return p ;
 case 2 : return q ;
 case 3 : return r ;
 case 4 : return s ;
 default : foo ( x+1);
 }
}

trong 5 biến p, x, q , r, s thì cái nào là tack cái nào là heap vậy?

1 Like

Bạn khai báo 1 con trỏ thì nó sẽ chiếm 4 bytes (32bit) hoặc 8 bytes (64bit) trên stack
Nhưng việc cấp phát vùng nhớ cho con trỏ thì vùng nhớ đó nằm trên Heap

VD:

int *ptr; 
\\ Trên stack sẽ chiếm 4 bytes cho con trỏ này đối với platform 32bit

ptr = malloc(4 * sizeof(int));
 \\ Một vùng nhớ 16 bytes sẽ được cấp phát trên Heap và ptr sẽ trỏ đến vùng nhớ này 
3 Likes

@small_hulk cho ví dụ đi, Đạt sẽ giải thích cụ thể cái nào nằm ở đâu :smiley:

Hoặc có thể xem ví dụ này:

void foo()
{
    int DayNhauHoc; // stack
    int * pointer; // stack
    pointer = &DayNhauHoc; // trỏ tới stack
    
    int * dynamic_allocate; // stack
    dynamic_allocate = (int*)malloc(sizeof(int)); // trỏ tới heap
}

Cụ thể các biến được tạo ra trong hàm trên đều được tạo ra trên stack, vùng nhớ mà biến pointer trỏ tới cũng nằm trên stack.

Riêng có vùng nhớ mà biến dynamic_allocate trỏ tới là nằm trên heap. Bời vì vùng nhớ đó được cấp phát động.

4 Likes

Các biến khai báo toàn cục, trong chương trình con hay trong tham số của chương trình con là những biến tĩnh, nằm ở vùng nhớ tĩnh (ví dụ: int x; float y; char z; short *a;). Các biến tĩnh khi khai báo thì đã được cấp phát vùng nhớ.
Vùng nhớ động chứa các “biến động”. Các biến động không có tên mà được quản lý bởi các biến con trỏ (pointer). biến con trõ nằm trong vùng nhớ tĩnh!

3 Likes
int p[10];
int foo(int x) {
 static int q [10] ;
 int r [10] ;
 int s = new int [10] ;
 switch ( x ) {
 case 1 : return p ;
 case 2 : return q ;
 case 3 : return r ;
 case 4 : return s ;
 default : foo ( x+1);
}

}
trong 5 biến p, x, q , r, s thì cái nào là tack cái nào là heap vậy?

1 Like

p: stack
x: stack
q: là biến static nên không thuộc vào stack hay heap.
Nếu q đã khởi tạo thì nằm trong BSS, còn chưa khởi tạo thì nằm trong .DATA. Trong trường hợp này chưa khởi tạo.
r: stack
s: stack
Chú ý: s trỏ tới vùng nhớ được tạo trong heap, nhưng bản thân s nằm trong stack.

6 Likes

mình chỉ mới biết biến con trỏ là thuộc vùng nhớ tĩnh còn lại thuộc heap
nhưng mà có 1 lưu ý trc khi trỏ con trỏ đến điểm nào đó thì nó thuộc stack nhưng sau khi trỏ đến điểm đó thuuộc heap thì nó lại nằm ở heap./

1 Like

@ltd
bài này mình có hỏi một số bạn, các bạn đó cho biết là chỉ có r là heap còn lại là stack.
@ltd bạn nghĩ sao về điều này?

1 Like

Các bạn đọc thêm tài liệu ở đây: http://www.inf.udec.cl/~leo/teoX.pdf

Khi một chương trình được thực thì bộ nhớ nó được chia ra làm 4 phần:

  1. Code segment hay text segment: Để lưu trữ code thực thi
  2. Data segment được chia làm 2 phần nhỏ:
    • Initialized data segment: chứa biến toàn cục (global), static và biến const
    • Uninitialized data segment(BSS): chứa các biến như Initialized data segment nhưng chưa được khởi tạo
  3. Heap: Chứa các vùng nhớ được cấp phát bởi malloc, calloc
  4. Stack: chứa các biến cục bộ (local variables), các tham số khi gọi hàm (arguments), địa chỉ trả về để tiếp tục thực thi sau khi kết thúc hàm (return address)

PS: Một số chỗ khác thấy Heap cũng được xem là một phần trong Data segment

5 Likes

@tranhuanltv cho mình hỏi nếu trong một hàm bạn tạo ra 1 biến static thì sau khi ra khỏi scope thì biến đó có bị xóa không? hay nó vẫn tồn tại và có time to live bằng với chương trình chính

1 Like

Câu này không đúng, con trỏ vẫn nằm ở stack. Nhưng vùng nó trỏ đến là heap. Giống như em đứng trên bờ nhưng thả câu xuống nước vậy.

1 Like

r không thể nào là heap, r là stack.

2 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?