Valgrind shows std::vector<> times of alloc is more than free, but no memory leak
Asked Answered
C

3

3

The code is fairly simple:

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

Then I build and run it with Valgrind:

g++ test.cc && valgrind ./a.out
==8511== Memcheck, a memory error detector
==8511== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==8511== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==8511== Command: ./a.out
==8511==
==8511==
==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== Rerun with --leak-check=full to see details of leaked memory
==8511==
==8511== For counts of detected and suppressed errors, rerun with: -v
==8511== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

The question is two-fold:

(1) "total heap usage" indicates that there is 1 alloc and 0 free. I assume that 1 alloc is because a std::vector instance needs a memory chunk in the heap. That's fine; but why doesn't it free the memory during destruction?

(2) And, if it doesn't free it, why is there no memory leak in "LEAK SUMMARY"?

(3) By the way, what does ==8511== before each line mean? (I could've look it up in the manual, though. You don't have to answer this)

Thanks!

Custombuilt answered 6/8, 2017 at 6:56 Comment(3)
Your question has absolutely nothing to do with C.Employee
Seems like Valgrind 3.11 has tried to fix this: bugzilla.redhat.com/show_bug.cgi?id=1312647Ratsbane
There are lots of things possibly allocated by C++. It has to create file handles and buffers for stdin, stdout, & stderr, and it likely creates a memory pool. Try removing the std::vector<> and see what valgrind saysOxen
L
5

Reported memory still in use by C++ runtime. You don't need to worry about it. Valgrind's FAQ has an entry regarding this problem:

First of all: relax, it's probably not a bug, but a feature. Many implementations of the C++ standard libraries use their own memory pool allocators. Memory for quite a number of destructed objects is not immediately freed and given back to the OS, but kept in the pool(s) for later re-use.

Linette answered 6/8, 2017 at 8:37 Comment(1)
@user8385554 - it's not the vector that really uses the memory, it's the libstdc++ runtime. Here's a bug describing what happens. Note that if you remove the vector v it goes away, but this is only because the linker then doesn't include libstdc++ at all since nothing needs it, so the global init never happens. If you compile with -O the "leak" also goes away since again the whole thing is optimized away.Disabuse
A
2

(1) A properly implemented default constructed std::vector doesn't allocate. Esp not 72k. Try running with --leak-check=full --track-origins=yes , perhaps it shows the origin of the allocation

(2) It says it, see: still reachable. The memory is not (yet) leaked, since there's still a handle (e.g: a pointer) pointing to it.

(3) It is the process id of the application.

Alarcon answered 6/8, 2017 at 9:0 Comment(0)
O
1

The 72kb you're seeing is allocated by the C++ runtime for its "emergency exception-handling pool". This pool is used to be able to allocate exception objects (such as bad_alloc exceptions) even when malloc can no longer allocate anything. We pre-allocate at startup, so if malloc runs out of memory we can still throw bad_alloc exceptions.

The specific number comes from this code:

       // Allocate the arena - we could add a GLIBCXX_EH_ARENA_SIZE environment
       // to make this tunable.
       arena_size = (EMERGENCY_OBJ_SIZE * EMERGENCY_OBJ_COUNT
                     + EMERGENCY_OBJ_COUNT * sizeof (__cxa_dependent_exception));
       arena = (char *)malloc (arena_size);

See https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/libsupc%2B%2B/eh_alloc.cc;h=005c28dbb1146c28715ac69f013ae41e3492f992;hb=HEAD#l117

Newer versions of valgrind know about this emergency EH pool and call a special function to free it right before the process exits, so that you don't see in use at exit: 72,704 bytes in 1 blocks. This was done because too many people fail to understand that memory still in use (and still reachable) is not a leak, and people kept complaining about it. So now valgrind frees it, just to stop people complaining. When not running under valgrind the pool doesn't get freed, because doing so is unnecessary (the OS will reclaim it when the process exits anyway).

Ophthalmia answered 5/4, 2019 at 13:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.