2010-12-30 44 views

Trả lời

41

Đầu tiên, phụ thuộc nền tảng. Trong một số kiến ​​trúc, ngăn xếp được phân bổ từ dưới cùng của không gian địa chỉ và phát triển lên trên.

Giả sử một kiến ​​trúc như x86 rằng Stack được trồng xuống từ phía trên cùng của không gian địa chỉ, ý tưởng là khá đơn giản:

===============  Highest Address (e.g. 0xFFFF) 
|    | 
| STACK | 
|    | 
|-------------| <- Stack Pointer (e.g. 0xEEEE) 
|    | 
.  ...  . 
|    | 
|-------------| <- Heap Pointer (e.g. 0x2222) 
|    | 
| HEAP  | 
|    | 
===============  Lowest Address (e.g. 0x0000) 

Để phát triển chồng, bạn muốn giảm con trỏ ngăn xếp:

===============  Highest Address (e.g. 0xFFFF) 
|    | 
| STACK | 
|    | 
|.............| <- Old Stack Pointer (e.g. 0xEEEE) 
|    | 
| Newly  | 
| allocated | 
|-------------| <- New Stack Pointer (e.g. 0xAAAA) 
.  ...  . 
|    | 
|-------------| <- Heap Pointer  (e.g. 0x2222) 
|    | 
| HEAP  | 
|    | 
===============  Lowest Address (e.g. 0x0000) 

Như bạn có thể thấy, để phát triển ngăn xếp, chúng tôi có đã giảm con trỏ ngăn xếp từ 0xEEEE xuống 0xAAAA, trong khi tăng heap, bạn phải tăng con trỏ heap.

Rõ ràng, đây là cách đơn giản hóa bố cục bộ nhớ. Phần thực thi, phần dữ liệu, ... cũng được tải trong bộ nhớ. Bên cạnh đó, chủ đề có không gian ngăn xếp của riêng họ.

Bạn có thể hỏi, tại sao ngăn xếp sẽ phát triển xuống dưới. Vâng, như tôi đã nói trước đây, một số kiến ​​trúc làm ngược lại, làm cho đống phát triển xuống và ngăn xếp tăng lên. Nó có ý nghĩa để đặt chồng và đống trên các cạnh đối diện vì nó ngăn chặn chồng lên nhau và cho phép cả hai khu vực phát triển tự do miễn là bạn có đủ không gian địa chỉ có sẵn.

Một câu hỏi hợp lệ khác có thể là: Chương trình không phải là giảm/tăng con trỏ ngăn xếp chính nó? Làm thế nào một kiến ​​trúc có thể đặt cái này lên cái kia cho lập trình viên? Tại sao nó không phụ thuộc vào chương trình vì nó phụ thuộc vào kiến ​​trúc? Trong khi bạn có thể chống lại kiến ​​trúc và bằng cách nào đó lấy đi chồng của bạn theo hướng ngược lại, một số hướng dẫn, đáng chú ý là callret sửa đổi con trỏ ngăn xếp trực tiếp sẽ giả định một hướng khác, tạo ra một mớ hỗn độn.

+4

+0.5 cho nghệ thuật ASCII một mình. :) Nhưng, trong khi trả lời "làm thế nào", điều này không trả lời "tại sao" rất tốt cả. Điều gì làm cho nó trở nên phổ biến và/hoặc hữu ích để xác định ngăn xếp theo cách này? – cHao

+2

@cHao: Đã thêm một vài đoạn để giải quyết vấn đề. –

+2

@Mehrdad Afshari Một số văn bản nói của nó bởi vì chúng tôi coulld giữ bù đắp không tiêu cực kể từ khi ngăn xếp phát triển xuống –

17

Ngày nay nó chủ yếu là vì nó được thực hiện theo cách đó trong một thời gian dài và rất nhiều chương trình giả định nó được thực hiện theo cách đó, và không có lý do thực sự để thay đổi nó.

Quay lại khi khủng long đi lang thang trên trái đất và máy tính có bộ nhớ 8kB nếu bạn may mắn, đó là một tối ưu hóa không gian quan trọng. Bạn đặt dưới cùng của ngăn xếp ở đầu của bộ nhớ, phát triển xuống, và bạn đặt chương trình và dữ liệu của nó ở phía dưới cùng, với khu vực malloc lớn lên. Bằng cách đó, giới hạn duy nhất về kích thước của chồng là kích thước của phần mềm + heap và ngược lại. Nếu ngăn xếp thay vì bắt đầu tại 4kB (ví dụ) và lớn lên, đống không bao giờ có thể lớn hơn 4kB (trừ kích thước của chương trình) ngay cả khi chương trình chỉ cần vài trăm byte chồng.

1
int main() { 
    int a = 0x12345678; 
    int b = 0x34234232; 
    printf("%p\n", &a); 
    printf("%p\n", &b); 
    return 0; 
} 

Chương trình này tạo kết quả này trên x86. Địa chỉ có nên giảm không?

[email protected]:~/eclipse_workspace/Sample/Sample$ ./a.out 
0xbf8a5f98 
0xbf8a5f9c 
[email protected]:~/eclipse_workspace/Sample/Sample$ 
+4

Mặc dù các biến cục bộ ** được lưu trữ trên ngăn xếp (trong C), chúng không được đẩy lên ngăn xếp theo cùng cách mà địa chỉ trả về cuộc gọi hàm. Thay vào đó, một đoạn của ngăn xếp được phân bổ tất cả cùng một lúc ngay sau khi hàm được gọi. Trình biên dịch sau đó gán một vị trí trong đoạn này cho mỗi biến cục bộ được khai báo. Làm thế nào trình biên dịch chọn để gán các biến trong phạm vi đó thay đổi theo trình biên dịch, mặc dù chúng thường đi vào bộ nhớ với thứ tự khai báo. Xem thêm [câu hỏi này] (http://stackoverflow.com/questions/1102049/order-of-local-variable-allocation-on-the-stack) –

+0

Đây không phải là câu trả lời cho câu hỏi. – problemofficer

Các vấn đề liên quan