2011-09-22 36 views
5

Trong chương trình C đơn giản của tôi (gnu linux) Tôi nhận được giá trị rss từ proc/stat.
int GetRSS() trả về giá trị RSS từ proc/stat cho quy trình của tôi.sự điên rồ là miễn phí()


Trong trường hợp này:

printf("A RSS=%i\n", GetRSS()); 
char *cStr = null; 
cStr = malloc(999999); 
if (cStr != NULL) 
{ 
    printf("B RSS=%i\n", GetRSS()); 
    free(cStr); 
    printf("C RSS=%i\n", GetRSS()); 
} 

tôi nhận được:

A RSS=980 
B RSS=984 
C RSS=980 

Tôi không thể giải thích tại sao C không trở về 984.


Nếu tôi chạy thủ tục tương tự hai lần tôi nhận được:

A RSS=980 
B RSS=984 
C RSS=980 
B RSS=984 
C RSS=980 

Trông tốt.


Nhưng, trong trường hợp này:

struct _test 
{ 
    char *pChar; 
} 
struct _test **test_ptr; 

int i = 0; 
printf("D RSS=%i\n",GetRSS()); 
assert(test_ptr = (struct _test **)malloc((10000) * sizeof(struct _test *))); 

for (i = 0; i < 1000; i++) 
{ 
    assert(test_ptr[i] = (struct _test *)malloc(sizeof(struct _test))); 
    test_ptr[i]->pChar=strdup("Some garbage"); 
} 

printf("E RSS=%i\n", GetRSS()); 

for (i=0; i<1000; i++) 
{ 
    free(test_ptr[i]->pChar); 
    free(test_ptr[i]); 
} 

free(test_ptr); 
printf("F RSS=%i\n", GetRSS()); 

tôi nhận được:

D RSS=980 
E RSS=1024 
F RSS=1024 
D RSS=1024 
E RSS=1024 
F RSS=1024 

Huh? Tại sao bộ nhớ không giải phóng ở đây?

+9

Bạn không bao giờ nên đặt các biểu thức có hiệu ứng phụ vào 'khẳng định'. –

+0

Đủ rồi. Phớt lờ nó đi. Tuy nhiên, kết quả là bối rối. –

+1

Chạy chương trình của bạn dưới "strace" để bạn có thể theo dõi các cuộc gọi mmap/munmap thực sự có ảnh hưởng đến giá trị RSS.Bạn có thể đặt một số printfs xung quanh mã để bạn có thể so khớp mmap/munmap với các điểm cụ thể của mã của bạn trong đầu ra. – vanza

Trả lời

5

Thực tế là một khối bộ nhớ đã được giải phóng không không nhất thiết làm cho khối đó đủ điều kiện nhất cho phân bổ tiếp theo. Có một số chiến lược cho người quản lý bộ nhớ để chọn một khối bộ nhớ (phù hợp nhất, phù hợp nhất, phù hợp nhất). Hầu hết các nhà quản lý bộ nhớ cũng cố gắng kết hợp các khối miễn phí, nhưng một số cố gắng để các khối miễn phí "tuổi" càng lâu càng tốt trước khi hợp nhất, trên lý thuyết rằng khi họ già đi, có cơ hội tốt hơn để chặn bên cạnh họ cũng được giải phóng, cải thiện tỷ lệ thành công tại các khối coalescing (do đó giảm phân mảnh).

Thực tế là khối không được sử dụng để đáp ứng yêu cầu phân bổ tiếp theo của bạn không không có nghĩa là nó không được giải phóng.

1

Thư viện malloc của bạn đã chọn không làm điều đó. Nó có thể là vì lý do chiến lược (để tránh phải truy cập vào hệ thống để có thêm bộ nhớ sau) hoặc có thể do những hạn chế (trong nguyên nhân cụ thể đó, nó không nhận ra rằng nó có thể giải phóng bộ nhớ).

Nói chung, điều đó không quan trọng. Không gian địa chỉ và bộ nhớ ảo thường không được coi là tài nguyên khan hiếm. Vì vậy, nỗ lực quá mức để giảm thiểu tiêu thụ của họ nói chung là vô giá trị tốt nhất và thường có hại.

2

Từ trang free() người đàn ông: "Thỉnh thoảng, miễn phí thực sự có thể trả lại bộ nhớ cho hệ điều hành và làm cho quy trình nhỏ hơn. Thông thường, tất cả những gì có thể làm là cho phép cuộc gọi sau này đến malloc để sử dụng lại không gian. không gian còn lại trong chương trình của bạn như một phần của danh sách miễn phí được sử dụng trong nội bộ bởi malloc. "

+0

Trong trường hợp của chương trình thực mà sinh ra câu hỏi này, nó cuối cùng đã hết bộ nhớ và bị treo. Thử nghiệm của tôi cho thấy bộ nhớ được phân bổ cho cấu trúc không được phát hành. Hơn nữa, strace không hiển thị các cuộc gọi mmap2 hoặc munmap liên kết với malloc và không có cấu trúc (và char * của nó). Tôi vẫn còn bối rối. –

+0

@MarkRichards: Tôi vừa bước qua chương trình của bạn trong WinDbg (không có một máy linux tiện dụng để chơi bây giờ), kiểm tra bộ nhớ đã cam kết với '! Heap'. Nó hoạt động tốt. Dường như không có bất kỳ rò rỉ bộ nhớ nào. Hãy nhớ rằng 'malloc' và' free' của glibc không cần gọi mmap/munmap, vì đã có bộ nhớ chưa được dành riêng cho vùng CRTs. Điều gì làm bạn có nghĩa là cuối cùng chạy ra khỏi bộ nhớ và tai nạn? Bạn có thể ghi đè toàn bộ chương trình không? –

+0

Rất thú vị. Tôi sẽ làm tương tự trên một hộp khác. Tôi đã sửa đổi chương trình - loại bỏ malloc đầu tiên, làm việc. Vẫn không gọi được mmap. xem: http://pastebin.com/m3gAJBhs –

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