Liệu free () hủy ánh xạ bộ nhớ của một tiến trình?


8

Tôi đang chạy chương trình C trên kernel Linux 2.6.16. Tôi không nghĩ rằng có sự rò rỉ bộ nhớ trong chương trình của mình tuy nhiên mức tiêu thụ bộ nhớ cho chương trình vẫn ổn định sau một số thao tác nhất định và không giảm. Tôi sử dụng lệnh 'ps v' để theo dõi giá trị RSS của chương trình của mình.

Công cụ khối lượng valgrind cho thấy một phần lớn của heap được phân bổ bởi mmap trong quy trình của tôi. Nhưng theo mã, các phân bổ đó đã được giải phóng sau khi các hoạt động được thực hiện. Có phải vì bộ nhớ đã giải phóng vẫn được ánh xạ và / hoặc vẫn đóng góp vào giá trị RSS của quá trình?

Bất kỳ cái nhìn sâu sắc sẽ được đánh giá rất cao!

Dưới đây là snip từ báo cáo khối lượng valgrind. Lưu ý Tôi đã bật tùy chọn --pages-as-heap cho công cụ massif để đo tất cả các bộ nhớ được sử dụng bởi chương trình.

--------------------------------------------------------------------------------
  n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
 85 701,483,989,262      173,576,192      173,576,192             0            0
 86 704,352,949,469      173,367,296      173,367,296             0            0
 87 707,582,275,643      173,367,296      173,367,296             0            0
 88 710,536,145,814      173,367,296      173,367,296             0            0
100.00% (173,367,296B) (page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc.
->53.40% (92,581,888B) 0x649248B: mmap (in /lib64/tls/libc.so.6)
| ->41.13% (71,303,168B) 0x6446D85: _int_malloc (in /lib64/tls/libc.so.6)
| | ->39.31% (68,157,440B) 0x6448D62: calloc (in /lib64/tls/libc.so.6)
......[my own functions are omitted]
->35.28% (61,157,376B) 0x400F51B: mmap (in /lib64/ld-2.3.3.so)
| ->28.81% (49,954,816B) 0x4004CE8: _dl_map_object_from_fd (in /lib64/ld-2.3.3.so)
| | ->28.81% (49,954,816B) 0x400636B: _dl_map_object (in /lib64/ld-2.3.3.so)
| |   ->18.89% (32,755,712B) 0x400AB42: openaux (in /lib64/ld-2.3.3.so)
| |   | ->18.89% (32,755,712B) 0x400AF7C: _dl_catch_error (in /lib64/ld-2.3.3.so)
| |   |   ->18.89% (32,755,712B) 0x4009FCF: _dl_map_object_deps (in /lib64/ld-2.3.3.so)
| |   |     ->18.89% (32,755,712B) 0x40021FD: dl_main (in /lib64/ld-2.3.3.so)
| |   |       ->18.89% (32,755,712B) 0x400E7F6: _dl_sysdep_start (in /lib64/ld-2.3.3.so)
| |   |         ->18.89% (32,755,712B) 0x4001477: _dl_start (in /lib64/ld-2.3.3.so)
| |   |           ->18.89% (32,755,712B) 0x4000CF6: ??? (in /lib64/ld-2.3.3.so)
| |   |             ->18.89% (32,755,712B) 0x0: ???
| |   |               ->18.89% (32,755,712B) 0x7FF0003D5: ???
| |   |                 ->18.89% (32,755,712B) 0x7FF0003E4: ???
| |   |
......

Tại sao bạn không sử dụng munmap? munmap (2)
Mikel

Bạn đang sử dụng thư viện chia sẻ? Bạn có thể cung cấp các phần có liên quan của đầu ra valgrindcũng như /proc/<PID>/maps?
Mikel

Chúng tôi không sử dụng munmap vì malloc glibc và miễn phí có triển khai. Có thư viện chia sẻ được sử dụng. Tại sao lại là vấn đề đó? Các phần có liên quan của báo cáo valgrind được thêm vào câu hỏi chính.
michelle


@michelle Tôi nghĩ bạn có nghĩa là bạn đang gọi mmap. Nhưng bây giờ tôi nghĩ rằng tôi hiểu: Bạn đang gọi malloc/ calloc, và nó đang gọi mmap?
Mikel

Câu trả lời:


5

Hàm thư viện C free()có thể, nhưng không phải trả lại bộ nhớ cho kernel.

Một số triển khai malloc()di chuyển ranh giới giữa "heap" và không gian địa chỉ không được sử dụng ("ngắt hệ thống") thông qua lệnh sbrk()gọi hệ thống, sau đó loại bỏ các phần nhỏ hơn của các phân bổ lớn đó. Nếu không được phân bổ lại từng phần nhỏ hơn, free()thực sự không thể trả lại bộ nhớ cho HĐH.

Lý do tương tự cũng áp dụng cho các malloc()triển khai không sử dụng sbrk(2), nhưng có thể sử dụng mmap("/dev/zero")hoặc một cái gì đó .. Tôi không thể tìm thấy tài liệu tham khảo, nhưng tôi dường như nhớ rằng một hoặc một trong những BSD đã sử dụng mmap()cách đó để lấy các trang bộ nhớ. Tuy nhiên, free()không thể trả lại một trang cho hệ điều hành trừ khi mọi phân bổ phụ được chương trình xử lý.

Một số malloc()triển khai thực hiện trả lại bộ nhớ cho hệ thống: ChorusOS (?) Rõ ràng đã làm. Không rõ nếu nó di chuyển hệ thống, hoặc munmap()'edcác trang.

Đây là một bài viết về bộ cấp phát bộ nhớ giúp cải thiện hiệu suất bằng cách "tích cực từ bỏ các trang miễn phí cho trình quản lý bộ nhớ ảo". Trình chiếu cho một cuộc nói chuyện về người cấp phát.


Tôi hiểu free () không trả lại ký ức cho HĐH. Nhưng liệu free () hủy ánh xạ bộ nhớ hay bộ nhớ vẫn được ánh xạ bởi bộ cấp phát bộ nhớ glibc?
michelle

"free () không thể trả lại một trang cho hệ điều hành trừ khi mọi phân bổ phụ được chương trình phân bổ lại." Tôi không thực sự hiểu điều này. Bạn có thể giải thích 'phân bổ phụ' không?
michelle

1
@michelle: giả sử kích thước trang là 4192 byte. Một chương trình gọi malloc (4186) và sau đó là malloc (8). Chương trình đã phân bổ tất cả một trang. Chương trình gọi free () trên phân bổ 4186 byte. free () không thể hủy ánh xạ trang vì phân bổ 8 byte chưa được free () 'ed.
Bruce Ediger

Điều đó có ý nghĩa. Cảm ơn Bruce. Vì vậy, dự đoán của tôi là khi trang vẫn được ánh xạ, tất cả dữ liệu trong đó vẫn được xem xét bằng phép đo valgrind mặc dù một số đã được giải phóng. Chính xác?
michelle
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.