2014-10-16 14 views
6

Đây là điều mà tôi đã tự hỏi trong một thời gian và không bao giờ tìm thấy một câu trả lời cho:C++ kích thước bộ nhớ động tại Runtime

Tại sao nó rằng khi bạn phân bổ một cái gì đó trên heap bạn không thể xác định kích thước của nó từ chỉ là con trỏ, nhưng bạn có thể xóa nó bằng cách sử dụng chỉ là con trỏ và bằng cách nào đó C + + biết bao nhiêu byte miễn phí?

Điều này có liên quan gì đến cách lưu trữ trên heap không? Thông tin này có ở đó nhưng không bị C++ tiếp xúc?

Và có lẽ đây sẽ là một câu hỏi riêng biệt nhưng tôi nghĩ rằng nó khá liên quan vì vậy tôi sẽ hỏi nó ở đây:

Tại sao nó một mảng động của các yếu tố phải được xóa bằng delete [] như trái ngược với chỉ đơn giản delete chỉ huy; tại sao C++ cần thông tin bổ sung này để giải phóng chính xác tất cả bộ nhớ?

+2

http://stackoverflow.com/questions/197675/how-does-delete-know-the-size-of-the-operand-array – taocp

+0

Đó là trình quản lý bộ nhớ OS đang xử lý mọi thứ. – dtech

+1

Đối với mảng, trình biên dịch C++ và thời gian chạy có quyền truy cập "riêng tư" đối với mảng dài bao lâu để gọi số lượng các trình phá hủy thích hợp nếu cần thiết. Ngoài ra http://stackoverflow.com/questions/11049144/is-the-size-of-a-dynamically-allocated-array-stored-somewhere/11049350#11049350 – dtech

Trả lời

5

Khi phân bổ được thực hiện, một phần nhỏ bộ nhớ ngay trước [hoặc, về mặt kỹ thuật, ở đâu đó hoàn toàn khác, nhưng trước đây là trường hợp phổ biến nhất] sẽ lưu trữ kích thước phân bổ và trong trường hợp new [] cũng lưu trữ số lượng các đối tượng được phân bổ. Lưu ý rằng tiêu chuẩn C++ không cung cấp bất kỳ cách nào để lấy thông tin này vì một lý do: Nó có thể không mô tả chính xác những gì được phân bổ, ví dụ kích thước của một mảng có thể được làm tròn thành một số "đẹp" ranh giới [hầu như tất cả các bộ phân bổ hiện đại có kích thước tối thiểu là 16 byte, do đó bộ nhớ có thể sử dụng cho SSE và các triển khai SIMD tương tự khác trên các kiến ​​trúc bộ vi xử lý khác]. Vì vậy, nếu bạn phân bổ 40 byte, nó sẽ báo cáo lại 48, mà không phải là những gì bạn yêu cầu, do đó, nó sẽ được khá khó hiểu. Và tất nhiên, không có gì đảm bảo rằng thông tin được lưu trữ tại TẤT CẢ - nó có thể được ngụ ý bởi một số thông tin khác được lưu trữ trong khối "quản trị" của phân bổ. Và tất nhiên, bạn có thể sử dụng vị trí new, trong trường hợp không có khối quản trị và phân bổ không bị xóa theo cách thông thường - một số mã tùy ý sẽ không thể cho biết sự khác biệt.

delete khác với delete [] trong đó delete [] sẽ biết số lượng đối tượng đã được phân bổ và gọi hàm hủy cho tất cả các đối tượng đó. Nó cũng có thể [hoặc thậm chí có khả năng] rằng new [] lưu trữ số lượng các yếu tố theo cách có nghĩa là gọi delete [] vào thứ gì đó không được tạo ra với new [] sẽ bị lỗi nghiêm trọng. Và như Zan Lynx nhận xét, rằng nếu không có destructor cho các đối tượng (ví dụ: khi bạn đang phân bổ dữ liệu cho int hoặc struct { int x; double y; }, v.v. - bao gồm các lớp không có hàm tạo lớp bên trong lớp, trình biên dịch sẽ xây dựng một destructor cho bạn]), sau đó không cần phải lưu trữ số, hoặc làm bất cứ điều gì khác, vì vậy trình biên dịch CÓ THỂ, nếu nó muốn, tối ưu hóa phân loại này vào thường xuyên newdelete .

+0

'new []' và 'delete []' cũng được tối ưu hóa để không bao giờ lưu trữ độ dài khi loại là POD (dữ liệu cũ thuần túy) vì nó không bao giờ phải gọi destructors sau đó. –

+0

Chính xác những gì tôi muốn biết. Cảm ơn bạn. :) – Matt

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