13

By checking with valgrind, I see that 5 blocks of memory were not freed after terminating my program, but they are still reachable. Do I need to be bothered by it?

And how it happens?

zhanwu@gelata:~/sandbox$ valgrind ./a.out
==2430== Memcheck, a memory error detector
==2430== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==2430== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==2430== Command: ./a.out
==2430== 
Hello world!
Thread1 returns 1
Thread2 returns 10
Thread3 returns 10
==2430== 
==2430== HEAP SUMMARY:
==2430==     in use at exit: 1,590 bytes in 5 blocks
==2430==   total heap usage: 14 allocs, 9 frees, 2,442 bytes allocated
==2430== 
==2430== LEAK SUMMARY:
==2430==    definitely lost: 0 bytes in 0 blocks
==2430==    indirectly lost: 0 bytes in 0 blocks
==2430==      possibly lost: 0 bytes in 0 blocks
==2430==    still reachable: 1,590 bytes in 5 blocks
==2430==         suppressed: 0 bytes in 0 blocks
==2430== Rerun with --leak-check=full to see details of leaked memory
==2430== 
==2430== For counts of detected and suppressed errors, rerun with: -v
==2430== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)

Below is my code, what can I do to free those 5 blocks if I intend to?

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;

void* myfunction(void *ptr)
{
    static int n_call = 0;
    int *retval = malloc(sizeof(int));

    pthread_mutex_lock( &mutex1 );
    n_call++;
    *retval = n_call;
    pthread_mutex_unlock( &mutex1 );

    if(n_call < 2)
    {
        char *msg;
        msg = (char *)ptr;
        printf("%s\n", msg);

        return retval;
    }
    else
    {
        *retval = 10;
        pthread_exit(retval);
    }
}

int main(int argc, char *argv[])
{
    pthread_t t1, t2, t3;

    char *msg = "Hello world!";
    pthread_create(&t1, NULL, myfunction, (void *)msg);
    pthread_create(&t2, NULL, myfunction, (void *)msg);
    pthread_create(&t3, NULL, myfunction, (void *)msg);

    int **s1 = malloc(sizeof(int*));
    int **s2 = malloc(sizeof(int*));
    int **s3 = malloc(sizeof(int*));

    pthread_join(t1, (void **)s1);
    pthread_join(t2, (void **)s2);
    pthread_join(t3, (void **)s3);

    printf("Thread1 returns %d\n", **s1);
    printf("Thread2 returns %d\n", **s2);
    printf("Thread3 returns %d\n", **s3);

    free(*s1);
    free(*s2);
    free(*s3);

    free(s1);
    free(s2);
    free(s3);

    return 0;
}
zhanwu
  • 1,508
  • 5
  • 16
  • 27

2 Answers2

20

No it is not a memory leak.
It means your program still has reference to memory that will freed later.

Valgrind FAQ differentiates between different messages as follows:

With Memcheck's memory leak detector, what's the difference between "definitely lost", "indirectly lost", "possibly lost", "still reachable", and "suppressed"?

The details are in the Memcheck section of the user manual.

In short:

  • definitely lost means your program is leaking memory -- fix those leaks!

  • indirectly lost means your program is leaking memory in a pointer-based structure. (E.g. if the root node of a binary tree is "definitely lost", all the children will be "indirectly lost".) If you fix the definitely lost leaks, the indirectly lost leaks should go away.

  • possibly lost means your program is leaking memory, unless you're doing funny things with pointers. This is sometimes reasonable.
    Use --show-possibly-lost=no if you don't want to see these reports.

  • still reachable means your program is probably ok -- it didn't free some memory it could have. This is quite common and often reasonable.
    Don't use --show-reachable=yes if you don't want to see these reports.

  • suppressed means that a leak error has been suppressed. There are some suppressions in the default suppression files. You can ignore suppressed errors.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • @zhanwu Valgrind does this check right before the program exits. – nos Oct 25 '11 at 07:50
  • @nos does it means that the program actually *freed* the memory but valgrind didn't capture it ? – zhanwu Oct 25 '11 at 08:04
  • @Als sorry I don't understand. Despite the reason why the program did not free the memory, the fact is that the memory is not freed, then who is in charge of this memory? My program exited, the memory is still reachable by whom? – zhanwu Oct 25 '11 at 08:11
  • @zhanwu Valgrind shows memory *you* have not released/freed, not what the OS automatically releases when the process exits. – nos Oct 25 '11 at 08:28
  • 3
    @zhanwu: It's memory that wasn't freed, but *could* have been freed if you'd wanted to, because the program still had pointers to it when it exited. – caf Oct 25 '11 at 10:00
  • @caf sorry to revive this old question, I have not understood also, he has used "free" command before exiting for s1,2,3. Does the report refer to "retval" which is malloc -ed ? So retval still has pointers before exiting but the user didn free it. – thahgr Sep 16 '16 at 12:52
  • 1
    @thahgr: In this case it's apparently referring to memory that the C library has allocated internally. – caf Sep 17 '16 at 13:32
1

It depends.

It may well be a real leak, and it might not. But either way you should fix it.

If you allocate a buffer and keep it around all the way to the end of the program, technically it's a leak, but it doesn't matter - you only allocate one buffer, and it's basically permanent.

On the other hand perhaps you are allocating a buffer in a way that it's done just once in your test code, but later with the real code it might get allocated more than once - then you have a leak.

So it's best to fix them all.

Ariel
  • 25,995
  • 5
  • 59
  • 69
  • Not sure about 'technically a leak'; it's perfectly acceptable to allow the OS to deallocate memory at program termination, especially if it's a big bugger allocated at startup. It's only a leak if memory isn't intentionally left allocated. – Phil Lello Oct 25 '11 at 08:20
  • @PhilLello yes, of course. I thought I said that. But you have to be sure that that is what you are doing, and that you don't accidentally allocate the memory more than once. However, IMO it's better to deallocate manually, it avoids trouble since who knows how the code will be changed later. – Ariel Oct 25 '11 at 08:28