简体   繁体   中英

What happens to globally allocated memory?

I have a program like this:

int *number0 = new int;

int main()
{
    int *number1 = new int;
}

I thought, both memory allocations would introduce memory leaks, though valgrind only complains about number1 inside the main function. Why is that?

Valgrind is not a perfect tool for detecting the presence or absence of all possible memory leaks, but rather a helpful tool that can detect some memory leaks. This means that valgrind output cannot be used to determine whether a particular piece of code contains or does not contain any leaks.

Neither of your new s have corresponding delete s, and in that sense, they are both leaked.

It is likely that valgrind considers the number0 memory to not be leaked because the memory it points to is reachable at the end of the program execution. In contrast to this, number1 goes out of scope, and so the memory it points to is not reachable at the end of the execution of your program, and so valgrind considers it to be leaked.

Running this

int *x = new int;

int main()
{   
    return 0;
}

code (ie without the leak in the main, compiled with g++ 4.8.1) using valgrind (3.8.1) with ( -v --track-origins=yes --leak-check=full --show-reachable=yes ) I get:

==34301== 
==34301== HEAP SUMMARY:
==34301==     in use at exit: 4 bytes in 1 blocks
==34301==   total heap usage: 1 allocs, 0 frees, 4 bytes allocated
==34301== 
==34301== Searching for pointers to 1 not-freed blocks
==34301== Checked 189,064 bytes
==34301== 
==34301== 4 bytes in 1 blocks are still reachable in loss record 1 of 1
==34301==    at 0x4C2A879: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==34301== 
==34301== LEAK SUMMARY:
==34301==    definitely lost: 0 bytes in 0 blocks
==34301==    indirectly lost: 0 bytes in 0 blocks
==34301==      possibly lost: 0 bytes in 0 blocks
==34301==    still reachable: 4 bytes in 1 blocks
==34301==         suppressed: 0 bytes in 0 blocks

Which means that you should also pay attention to the in use at exit category.

It doesn't seem like valgrind missed it, just placed it in another category, possibly because they assume something as lost only when you cannot by any means track down that address and release it, but this variable is never lost .

This however :

int *x = new int;

int main()
{

    x = new int;    
    return 0;
}

Is detected as a leak as you really lose track of the memory you've allocated.

EDIT: As described in the Mem-check manual :

"Still reachable". This covers cases 1 and 2 (for the BBB blocks) above. A start-pointer or chain of start-pointers to the block is found. Since the block is still pointed at, the programmer could, at least in principle, have freed it before program exit. "Still reachable" blocks are very common and arguably not a problem. So, by default, Memcheck won't report such blocks individually.

So as noted before they do detect it, they just think it's less exciting

I see two leaks using valgrind 3.8.1 / g++ 4.8.1:

$ g++ -o foo -g foo.cc
$ valgrind ./foo
...
==7789== HEAP SUMMARY:
==7789==     in use at exit: 8 bytes in 2 blocks
==7789==   total heap usage: 2 allocs, 0 frees, 8 bytes allocated
==7789== 
==7789== LEAK SUMMARY:
==7789==    definitely lost: 4 bytes in 1 blocks
==7789==    indirectly lost: 0 bytes in 0 blocks
==7789==      possibly lost: 0 bytes in 0 blocks
==7789==    still reachable: 4 bytes in 1 blocks
==7789==         suppressed: 0 bytes in 0 blocks

The "definitely lost" bytes are in main in my test.

This

  int *number0 = new int;

is not a memory leak because it gets reclaimed at the end of execution.

This configuration is a [potential] memory leak because

int main()
{
     int *number1 = new int;
}

some other part of the code could call

    main () ;

and it could be called repeatedly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM