2010-08-19 34 views
5

Sửa đổi:Địa chỉ của Ngăn xếp và Heap trong C++

Tôi đã nhầm lẫn với khái niệm địa chỉ con trỏ và địa chỉ con trỏ trỏ tới, vì vậy mã sau đây đã được sửa đổi. Và bây giờ nó in ra những gì tôi muốn, biến a, c, i, j, k, p là trên ngăn xếp, và biến b, d là trên đống. Các biến tĩnh và toàn cục nằm trên một phân đoạn khác. Cảm ơn rất nhiều vì tất cả các bạn!


Vâng, tôi biết rằng hai khái niệm này sẽ được thảo luận sâu sắc ... nhưng tôi vẫn còn thắc mắc cho đoạn mã sau:

#include <iostream> 
using namespace std; 

class A { 

}; 

int N = 10; 

void f(int p) { 
    int j = 1; 
    float k = 2.0; 
    A c; 
    A* d = new A(); 
    static int l = 23; 
    static int m = 24; 
    cout << "&c: " << &c << endl; 
    cout << "&d: " << d << endl; 
    cout << "&j: " << &j << endl; 
    cout << "&k: " << &k << endl; 
    cout << "&l: " << &l << endl; 
    cout << "&m: " << &m << endl; 
    cout << "&p: " << &p << endl; 
} 

int main() { 
    int i = 0; 
    A* a; 
    A* b = new A(); 
    cout << "&a: " << &a << endl; 
    cout << "&b: " << b << endl; 
    cout << "&i: " << &i << endl; 
    cout << "&N: " << &N << endl; 
    f(10); 
    return 0; 
} 

kết quả của tôi là:

&a: 0x28ff20 
&b: 0x7c2990 
&i: 0x28ff1c 
&N: 0x443000 
&c: 0x28fef3 
&d: 0x7c0f00 
&j: 0x28feec 
&k: 0x28fee8 
&l: 0x443004 
&m: 0x443008 
&p: 0x28ff00 

này là khá thú vị, coz ngoại trừ biến toàn cầu N, và hai biến tĩnh trong hàm f, là l và m, địa chỉ của tất cả các biến khác dường như cùng nhau. (Lưu ý: Mã và kết quả đã được sửa đổi và không tương ứng với những gì được nói ở đây.)

Tôi đã tìm kiếm rất nhiều về ngăn xếp và đống. Ý nghĩa chung là, nếu một đối tượng được tạo ra bởi "mới", thì nó nằm trên heap. Và các biến cục bộ (như j và k trong mẫu trên) đang ở trên stack. Nhưng có vẻ như không phải là trường hợp trong ví dụ của tôi. Liệu nó phụ thuộc vào các trình biên dịch khác nhau, hoặc sự hiểu biết của tôi là sai?

Cảm ơn rất nhiều vì tất cả các bạn.

+0

Tôi không hiểu câu hỏi của bạn tại sao bạn cho rằng một biến nằm trên chồng hoặc đống dựa trên địa chỉ bạn đã hiển thị. –

+0

Điều này thực sự là vô nghĩa. Bạn không thể thực hiện bất kỳ loại suy luận về nơi bộ nhớ của bạn là – Falmarri

+0

có thể trùng lặp của [Sử dụng chồng và đống đúng cách trong C++?] (Http://stackoverflow.com/questions/599308/proper-stack-and-heap-usage -in-c) –

Trả lời

14

Hiểu biết của bạn sai. Ví dụ: b là con trỏ - nếu bạn muốn địa chỉ của đối tượng được tạo bởi new, bạn cần in ra b, không phải &b. b là một biến địa phương, do đó, nó tự nó (được tìm thấy tại &b) là trên ngăn xếp.

Ví dụ: N, lm có lẽ là một nơi nào đó trong phần dữ liệu thực thi của bạn. Như bạn thấy, họ có địa chỉ tương tự. Mỗi biến khác bạn đang in ra nằm trên ngăn xếp - địa chỉ của chúng tương tự nhau. Một số người trong số họ là con trỏ trỏ đến các đối tượng được phân bổ từ heap, nhưng không có bản in nào của bạn sẽ hiển thị điều đó.

1

Nếu bạn muốn in địa chỉ của bất cứ điều gì d điểm đến (trong trường hợp này nó trỏ đến một đối tượng trên heap), làm

cout << "d: " << d << endl; 

Điều đó sẽ in giá trị của con trỏ, và giá trị của một con trỏ là địa chỉ của đối tượng mà nó trỏ đến.

Mã của bạn có

cout << "&d: " << &d << endl; 

này in địa chỉ của d, khi bạn định nghĩa d bên chính, nó sẽ được phát trên stack, bạn đang in địa chỉ của con trỏ của bạn. Có con trỏ chính nó, và đối tượng nó trỏ đến, chúng là 2 thứ riêng biệt, với các địa chỉ riêng biệt.

2

Hiểu biết của bạn là chính xác.

  • biến cục bộ được cấp phát trên ngăn xếp.
  • đối tượng được cấp động được cấp phát trên heap.

Mặc dù bạn đang sử dụng địa chỉ biến cục bộ nhất quán trong ví dụ của mình.
Ví dụ: in ra d không phải là địa chỉ d. Vì d là một biến cục bộ (do đó địa chỉ tương tự như c) nhưng nó là một biến con trỏ trỏ đến một đối tượng được phân bổ động (that is on the heap).

Trình biên dịch thực hiện ngăn xếp và đống mặc dù sẽ thay đổi như thế nào.

Trong hệ điều hành hiện đại, chồng và đống thậm chí có thể chia sẻ cùng một khu vực (nghĩa là bạn có thể triển khai ngăn xếp bằng cách phân bổ các đoạn trong heap).

+0

Điều này đúng, nhưng không phải lý do tại sao OP lại nhận được các giá trị mà anh ta có. :-) – Omnifarious

0

Sự khác biệt giữa hai hình thức, từ góc độ C++ thuần túy, chỉ liên quan đến thời gian quản lý đối tượng.

From here, good read

0

Biến tĩnh nằm trong phân đoạn dữ liệu. Ngoài ra bạn trộn địa chỉ của một con trỏ và nó có giá trị. Ví dụ:

a là biến cục bộ loại A * trên ngăn xếp. & cũng cung cấp địa chỉ nơi một actaully resieds (trên stack). Giá trị của a là địa chỉ của đối tượng heap thuộc loại A;

0

Bạn không thể phụ thuộc vào các trình biên dịch khác nhau làm việc theo cùng một cách. Đối với hầu như tất cả các bit của mã, bạn sẽ viết sự khác biệt giữa ngăn xếp và đống là vô nghĩa. Đừng lo lắng về điều đó.

2

Chỉ những người duy nhất không 'cùng nhau' trong ví dụ của bạn là l, mN. Chúng là hai số liệu thống kê và một số toàn cầu, do đó chúng không được phân bổ trên stack cho chắc chắn. Họ không phải là từ một heap không, rất có thể, họ là từ một phân đoạn .data của module của bạn. Người duy nhất từ ​​heap phải là địa chỉ b điểm đến, nhưng bạn đang in địa chỉ của b chính nó, không phải những gì nó trỏ đến.

+1

Cũng cần lưu ý rằng 'tính neirness' của bạn khá cụ thể. Các địa chỉ có thể trông hoàn toàn khác (ví dụ '& p' là 'xa' từ' & j') trên nền tảng như IA64 với ngăn xếp 'kho lưu trữ', xem http://blogs.msdn.com/b/slavao/ lưu trữ/2005/03/19/399117.aspx –

0

Có thể không giả định bất cứ điều gì về địa chỉ tương đối của các thứ trong ngăn xếp tương đối so với địa chỉ trên heap, cũng không phải là địa chỉ tương đối của bất kỳ con trỏ nào không bắt nguồn từ cùng mảng hoặc được phân bổ (qua khối malloc, calloc, v.v.) Tôi thậm chí không chắc chắn con trỏ được yêu cầu để được xếp hạng.

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