2011-03-17 32 views
13

Đây là trong C++ trên CentOS 64bit sử dụng G ++ 4.1.2.new [] không giảm bộ nhớ còn trống cho đến khi được điền

Chúng tôi đang viết một ứng dụng thử nghiệm để tải lên mức sử dụng bộ nhớ trên một hệ thống bằng n Gigabyte. Ý tưởng được rằng tải hệ thống tổng thể được giám sát thông qua SNMP vv Vì vậy, đây chỉ là một cách để thực hiện giám sát.

Những gì chúng ta đã nhìn thấy tuy nhiên là chỉ đơn giản là thực hiện:

char* p = new char[1000000000]; 

không ảnh hưởng đến bộ nhớ sử dụng như trình bày trong một trong hai đầu hoặc miễn phí -m

Việc phân bổ bộ nhớ chỉ dường như trở thành " thực "khi bộ nhớ được ghi vào:

memcpy(p, 'a', 1000000000); //shows an increase in mem usage of 1GB 

Nhưng chúng ta phải ghi vào tất cả bộ nhớ, chỉ cần viết vào phần tử đầu tiên sẽ không làm tăng bộ nhớ đã sử dụng:

p[0] = 'a'; //does not show an increase of 1GB. 

Điều này có bình thường, bộ nhớ thực sự được phân bổ đầy đủ chưa? Tôi không chắc đó có phải là công cụ chúng tôi đang sử dụng (top và free -m) đang hiển thị các giá trị không đúng hay liệu có cái gì đó thông minh đang diễn ra trong trình biên dịch hay trong thời gian chạy và/hoặc hạt nhân.

Hành vi này được nhìn thấy ngay cả trong bản dựng gỡ lỗi có tối ưu hóa bị tắt.

Đó là sự hiểu biết của tôi rằng một [] mới đã cấp phát bộ nhớ ngay lập tức. Thời gian chạy C++ có làm chậm trễ sự phân bổ thực sự này cho đến sau này khi nó được truy cập hay không. Trong trường hợp đó, có thể trì hoãn ngoại lệ bộ nhớ cho đến khi phân bổ bộ nhớ thực sự cho đến khi bộ nhớ được truy cập?

Vì nó không phải là một vấn đề đối với chúng tôi, nhưng nó sẽ là tốt đẹp để biết lý do tại sao điều này xảy ra theo cách của nó!

Chúc mừng!

Edit:

Tôi không muốn biết về cách chúng tôi nên sử dụng Vectors, đây không phải OO/C++/cách hiện làm việc vv vv Tôi chỉ muốn biết tại sao điều này là xảy ra theo cách của nó, thay vì có những gợi ý cho những cách khác để thử nó.

Trả lời

8

Vui lòng tra cứu quá mức. Linux theo mặc định không đặt trước bộ nhớ cho đến khi nó được truy cập. Và nếu bạn kết thúc bằng cách cần nhiều bộ nhớ hơn khả dụng, bạn không gặp lỗi nhưng một quá trình ngẫu nhiên bị giết. Bạn có thể kiểm soát hành vi này với /proc/sys/vm/*.

IMO, quá tải phải là một cài đặt cho mỗi quá trình, không phải là cài đặt toàn cầu. Và mặc định không nên quá thừa.

+0

Điều này! 1 cho câu trả lời đúng. –

17

Khi thư viện của bạn cấp phát bộ nhớ từ hệ điều hành, hệ điều hành sẽ chỉ dành một dải địa chỉ trong không gian địa chỉ ảo của quy trình. Không có lý do gì để hệ điều hành thực sự cung cấp bộ nhớ này cho đến khi bạn sử dụng nó - như bạn đã chứng minh.

Nếu bạn nhìn vào ví dụ: /proc/self/maps bạn sẽ thấy dải địa chỉ. Nếu bạn nhìn vào bộ nhớ hàng đầu , hãy sử dụng bạn sẽ không thấy nó - bạn chưa sử dụng.

+0

Tôi đã có một số kinh nghiệm về điều này và tôi nghĩ rằng các hiệp hội bộ nhớ và phương pháp thu gom rác thải trong trình biên dịch hiện đại cũng ảnh hưởng đến vấn đề này. Bạn có thông tin kỹ thuật về điều này không? – Hossein

+0

Không có bộ sưu tập rác trong C++ - nó không liên quan. Trong java hoặc C# có thể trong lý thuyết là một nguyên nhân bổ sung mặc dù. Để biết chi tiết, hãy bắt đầu với trang wikipedia trên * Không gian địa chỉ ảo * – Erik

+0

Tôi nghĩ đó là một tính năng phổ biến của Unix. Nó có thể có khả năng gây ra địa ngục, vì hệ thống làm cho ứng dụng của bạn tin rằng nó sẽ có thể đáp ứng các yêu cầu của nó nhưng sau đó có thể không ở trong một vị trí, tuy nhiên trong thực tế tôi cho rằng nó mang lại mức tiêu thụ bộ nhớ thấp hơn. –

2

Giới thiệu về nửa thứ hai của câu hỏi:

Tiêu chuẩn ngôn ngữ không cho phép bất kỳ sự chậm trễ nào khi ném bad_alloc. Điều đó phải xảy ra như là một thay thế cho new [] trả về một con trỏ. Nó không thể xảy ra sau!

Một số hệ điều hành có thể cố gắng vượt quá phân bổ bộ nhớ và không hoạt động sau. Điều đó không phù hợp với tiêu chuẩn ngôn ngữ C++.

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