Why don't memory operators return freed OS memory?

Yes, this may be the third time you see this code, because I asked two more questions ( this and this ) .. The code is pretty simple:

#include <vector>
int main() {
    std::vector<int> v;
}

Then I create and run it using Valgrind on Linux:

g++ test.cc && valgrind ./a.out
==8511== Memcheck, a memory error detector
...
==8511== HEAP SUMMARY:
==8511==     in use at exit: 72,704 bytes in 1 blocks
==8511==   total heap usage: 1 allocs, 0 frees, 72,704 bytes allocated
==8511==
==8511== LEAK SUMMARY:
==8511==    definitely lost: 0 bytes in 0 blocks
==8511==    indirectly lost: 0 bytes in 0 blocks
==8511==      possibly lost: 0 bytes in 0 blocks
==8511==    still reachable: 72,704 bytes in 1 blocks
==8511==         suppressed: 0 bytes in 0 blocks
...
==8511== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Here Valgrind reports that there is no memory leak, although there are 1 alloc and 0 for free.

The answer here indicates that the allocator used by the standard C ++ library does not necessarily return memory back to the OS - it may contain them in the internal cache.

Question:

1) Why store them in the internal cache? If it's speed, how is it faster? Yes, the OS must support a data structure in order to track memory allocation, but it must also support this cache.

2) ? a.out , , , , ?

: (2) - , , "++ runtime", ? "++ runtime" - ++, , , - a.out ( , .a) ( , .so) a.out.

+4
1

-, . :... a.out , , - , ?

, , : . , 1. - : " ", . , .

, Valgrind, - , , , . , . : ", , 72 000 , ", , " ".

Valgrind , . : , .

:

1) ? , ? , , .

: - userland, (?), , , .

?

  • , Linux Unix- , . Unix-alikes brk, - "" . mmap, , PAGE_SIZE, Linux 4096 . , 32 , 4096 - 32 == 4064 , . , , .

    Windows . HeapAlloc , "" malloc - . malloc HeapAlloc ( Windows, ). , HeapAlloc , - , , , . , malloc , , , .

  • ! , . , malloc , 10 . , " " , . free , , , ! free , .
  • . , ++, new, malloc , . , , , . , , . , , ​​ !

, , , , , / , OS . , , , . malloc. -, , - - , , .

? :

  • API . brk sbrk , , brk sbrk. , , , , . . , , brk, .

    mmap ( , , Windows, VirtualAlloc mmap), , ! , , . / , . , , - - , . , mmap, , mmap munmap. glibc ( ++) :

    M_MMAP_THRESHOLD
      For allocations greater than or equal to the limit specified
      (in bytes) by M_MMAP_THRESHOLD that can't be satisfied from
      the free list, the memory-allocation functions employ mmap(2)
      instead of increasing the program break using sbrk(2).
    
      Allocating memory using mmap(2) has the significant advantage
      that the allocated memory blocks can always be independently
      released back to the system.  (By contrast, the heap can be
      trimmed only if memory is freed at the top end.)  On the other
      hand, there are some disadvantages to the use of mmap(2):
      deallocated space is not placed on the free list for reuse by
      later allocations; memory may be wasted because mmap(2)
      allocations must be page-aligned; and the kernel must perform
      the expensive task of zeroing out memory allocated via
      mmap(2).  Balancing these factors leads to a default setting
      of 128*1024 for the M_MMAP_THRESHOLD parameter.
    

    , 128 . , , , , , .

  • ! , . , , , . , , , ? man-, , . , . , TLB, munmap (, , brk).
  • "" , - , , . I.e., , , . . , , , , . , ", " , , malloc_trim.
  • . , " ", , . , 2 , , , 2 DRAM, -? . 2 , , - , . - , (, DRAM) - . , - .

    - , , : madvise(..., MADV_DONTNEED), " , swap". - , , ( ), , munmap mmap, . 2

, vector<int> , , std::vector<int> v , . , vector , . , - , , , ~ 72 000 , Valgrind.

- , :

#include <vector>

volatile vector<int> *sink;

int main() {
    std::vector<int> v(12345678);
    sink = &v;
}

. Valgrind, , Valgrind.

Valgrind " " " ". , , . ​​ , , . , , "", .. , , , , , (- , , , , ).


1 , , ++, .

2 Linux Linux- MADV_FREE, , , MADV_DONTNEED.

+7

Source: https://habr.com/ru/post/1683133/


All Articles