2012-05-24 44 views
6

Tôi đang ở một chéo scratchbox lập môi trường và có điều nàyTại sao bộ nhớ của chương trình này không tăng?

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main() 
{ 
    int * ptr; 
    int i=0; 

    while(1) 
    { 
     ptr = (int*)malloc(10485760 * sizeof(int)); 

     if(ptr == NULL) 
     { 
      printf("Could not malloc\n"); 
      exit(1); 
     } 

     else 
     { 
      printf("Malloc done\n"); 
      for (i = 0 ; i <= 10485759 ; i++) 
      { 
       ptr[i] = i ; 
      } 
      sleep (5); 
      continue; 
     } 
    } 
} 

Khi tôi chạy nhị phân và làm

ps -p pid -o cmd,rss,%mem 

Tôi không thấy bất kỳ sự gia tăng trong bộ nhớ của quá trình. Tại sao vậy?

+0

vì bộ nhớ được cấp phát cùng một lúc ngay từ đầu? –

+3

@arasmussen Bên trong vòng lặp 'while'. –

+0

Có lẽ trình biên dịch thấy rằng bạn không còn có một xử lý trên con trỏ đó (bởi vì bạn viết ptr mỗi lần) và dọn dẹp sau nó cho bạn? Hoặc có thể mất nhiều thời gian để chạy mười triệu lần lặp lại? –

Trả lời

5

Bạn có thể đã xây dựng rất tối ưu.

Trên hầu hết các hệ thống hiện đại, gcc biết rằng malloc trả về một con trỏ không có biệt danh. Đó là để nói, nó sẽ không bao giờ trở lại cùng một con trỏ hai lần và nó sẽ không bao giờ trở lại một con trỏ bạn đã lưu 'sống' ở một nơi khác.

Tôi thấy điều này rất khó tưởng tượng, nhưng có thể là malloc đang được gọi một lần và giá trị trả về của nó được sử dụng hơn và hơn. Lý do là:

Nó biết bộ nhớ của bạn là một cửa hàng chết. tức là: bạn viết cho nó, nhưng nó không bao giờ được đọc từ đó. Con trỏ được biết là không được đặt bí danh vì vậy nó đã không thoát được để đọc từ một nơi khác, và nó không được đánh dấu dễ bay hơi. Vòng lặp for của bạn/có thể/bị vứt bỏ.

Tại thời điểm đó, nó chỉ có thể sử dụng cùng một bộ nhớ hơn và hơn.

Bây giờ, đây là lý do tại sao tôi thấy khó tin: Chỉ cần gcc biết bao nhiêu về malloc? Malloc có thể có bất kỳ loại tác dụng phụ nào như tăng số lần gọi là 'toàn cầu' để 'vẽ căn phòng của tôi một màu xanh dương ngẫu nhiên'. Nó có vẻ thực sự kỳ lạ rằng nó sẽ thả các cuộc gọi và giả sử nó được side-hiệu ứng miễn phí. Địa ngục, 'malloc' có thể được thực hiện để trả về NULL mỗi 100 cuộc gọi (có thể không hoàn toàn để spec, nhưng ai là để nói).

Điều bạn KHÔNG làm là giải phóng nó thay cho bạn. Điều đó vượt xa những gì nó 'có thể' biết và vào lãnh thổ của 'làm những điều nó chỉ không được phép'. Bạn được phép để rò rỉ bộ nhớ, lame mặc dù nó có thể được.

2 điều sẽ hữu ích ở đây: 1) Biên dịch environmenet: đó là os, trình biên dịch và cờ dòng lệnh.

và 2) tháo gỡ nhị phân cuối cùng. (objdump hoặc từ trình biên dịch)

+0

_Chỉ cần bao nhiêu gcc biết về malloc? _ Gcc được phép biết Tất cả mọi thứ về 'malloc()', vì C chuẩn xác định hành vi của hàm đó. – mlp

-2

Trình biên dịch của bạn đang giúp bạn bằng cách giải phóng bộ nhớ được cấp phát (giả sử rằng phiên bản được tối ưu hóa của mã của bạn thậm chí đi xung quanh để làm malloc) khi nó nhận ra bạn không sử dụng nó. Bạn có thể thử in ra giá trị của con trỏ (printf ("0x% x", ptr);) - Tôi nghi ngờ bạn sẽ nhận được các giá trị lặp lại. Một kiểm tra đáng tin cậy hơn sẽ viết một bitstring đã biết vào bộ nhớ, đã xem xét để xem bộ nhớ được cấp đã chứa chuỗi đó chưa. Nói cách khác, thay vì viết i, viết 0xdeadbeef0cabba6e lặp đi lặp lại, sau khi kiểm tra xem mẫu bit đó đã có trong không gian bạn đã phân bổ chưa.

+0

C thường không thực hiện loại thu gom rác đó trong thời gian chạy. Nhưng thật thú vị khi nghĩ về trình biên dịch * có thể làm gì. Không có 'ptr [i]' nào được đọc từ đó, do đó nhiệm vụ đó có thể được chọn lọc. Sau đó, không có bộ nhớ nào được phân bổ bởi 'malloc' được sử dụng theo bất kỳ cách nào, do đó, trong hiệu trưởng có thể được elided (nếu chúng tôi hài lòng rằng" số lượng bộ nhớ được phân bổ "không phải là một tài sản chính xác phải được bảo tồn). Tuy nhiên, cái đầu tiên có lẽ là khó khăn với việc đánh răng, và tôi sẽ ngạc nhiên nếu bất kỳ trình biên dịch C nào tồn tại làm điều thứ hai; không chắc chắn đó là một chuyển đổi hợp lệ anyway. – Edmund

+0

Tôi chưa bao giờ gợi ý rằng có bất kỳ bộ sưu tập rác nào xảy ra. Đặc tả C cho phép bất kỳ sự tối ưu hóa nào theo điều kiện duy nhất mà kết quả cuối cùng không có sự khác biệt chức năng so với định nghĩa của định nghĩa máy trừu tượng C. (Lưu ý rằng chúng ta không nói về một máy ảo theo nghĩa Java, nhưng theo nghĩa là C spec định nghĩa một máy trừu tượng như là một cơ chế để xác định hành vi của mã được biên dịch.) Nó sẽ là tốt trong phần trình tối ưu hóa của trình tối ưu hóa loại bỏ các phân bổ từ mã trên hoàn toàn. – Sniggerfardimungus

+0

"Bộ sưu tập rác" là quá trình đưa ra quyết định - trong thời gian chạy - về khi bộ nhớ không được thu nhận có thể được giải phóng. Chúng tôi không nói về một quyết định thời gian chạy ở đây, nhưng một hiệu ứng biên dịch thời gian để nhận thấy rằng các dữ liệu được phân bổ và ghi vào không bao giờ được sử dụng. – Sniggerfardimungus

2

rss và% mem cả về mặt "bộ nhớ vật lý đang được quá trình sử dụng tại thời điểm này". Nó có rất nhiều cơ hội để trang ra công cụ. Hãy thử thêm vsz. Tôi đặt cược rằng phát triển như bạn mong đợi.

+0

Bumping bạn lên. Nếu bạn giả định những gì tôi đã nói bên dưới về trình biên dịch có thể vứt bỏ vòng lặp gán như là một cửa hàng chết, bộ nhớ này sẽ được dành riêng nhưng không bao giờ cam kết và có thể lặp lại cho đến khi không gian địa chỉ hết; mà không bao giờ thực sự cam kết một byte. :) – Joe

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