Using valgrind to find a memory leak in the mysql c++ client

1k Views Asked by At

I'm using valgrind to try and track down a memory leak is the mysql c++ client distributed from mysql.

In both the examples (resultset.cpp) and my own program, there is a single 56 byte block that is not freed. In my own program, I've traced the leak to a call to the mysql client.

Here are the results when I run the test:

valgrind --leak-check=full --show-reachable=yes ./my-executable

==29858== Memcheck, a memory error detector
==29858== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==29858== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==29858== Command: ./my-executable
==29858==
==29858==
==29858== HEAP SUMMARY:
==29858==     in use at exit: 56 bytes in 1 blocks
==29858==   total heap usage: 693 allocs, 692 frees, 308,667 bytes allocated
==29858==
==29858== 56 bytes in 1 blocks are still reachable in loss record 1 of 1
==29858==    at 0x4C284A8: malloc (vg_replace_malloc.c:236)
==29858==    by 0x400D334: _dl_map_object_deps (dl-deps.c:506)
==29858==    by 0x4013652: dl_open_worker (dl-open.c:291)
==29858==    by 0x400E9C5: _dl_catch_error (dl-error.c:178)
==29858==    by 0x4012FF9: _dl_open (dl-open.c:583)
==29858==    by 0x7077BCF: do_dlopen (dl-libc.c:86)
==29858==    by 0x400E9C5: _dl_catch_error (dl-error.c:178)
==29858==    by 0x7077D26: __libc_dlopen_mode (dl-libc.c:47)
==29858==    by 0x72E5FEB: pthread_cancel_init (unwind-forcedunwind.c:53)
==29858==    by 0x72E614B: _Unwind_ForcedUnwind (unwind-forcedunwind.c:126)
==29858==    by 0x72E408F: __pthread_unwind (unwind.c:130)
==29858==    by 0x72DDEB4: pthread_exit (pthreadP.h:265)
==29858==
==29858== LEAK SUMMARY:
==29858==    definitely lost: 0 bytes in 0 blocks
==29858==    indirectly lost: 0 bytes in 0 blocks
==29858==      possibly lost: 0 bytes in 0 blocks
==29858==    still reachable: 56 bytes in 1 blocks
==29858==         suppressed: 0 bytes in 0 blocks
==29858==
==29858== For counts of detected and suppressed errors, rerun with: -v
==29858== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 8 from 6)

I have a few questions regarding this:

  1. How should I interpret the --show-reachable block?
  2. Is that block useful for me to try and zero in on the error?
  3. If the block is not useful, does valgrind have another mechanism that would help me trace the leak?
  4. If not, is there some other tool (hopefully OSS on linux) to help me narrow this down?

Thanks in advance..

UPDATE: Here is the code that I found on my system for the definition of pthread_exit. I'm not certain that this is the actual source that is being invoked. However, if it is, can anyone explain what might be going wrong?

void
pthread_exit (void *retval)
{
    /*  specific to PTHREAD_TO_WINTHREAD  */

    ExitThread ((DWORD) ((size_t) retval));  /*  thread becomes signalled so its death can be waited upon  */
    /*NOTREACHED*/
    assert (0); return;  /*  void fnc; can't return an error code  */
}
1

There are 1 best solutions below

7
On BEST ANSWER

Reachable just means that the blocks had a valid pointer referencing them in scope when the program exited, which indicates that the program does not explicitly free everything on exit because it relies on the underlying OS to do so. What you should be looking for are lost blocks, where blocks of memory lost all references to them and can no longer be freed.

So, the 56 bytes were probably allocated in main, which did not explicitly free them. What you posted does not show a memory leak. It shows main freeing everything but what main allocated because main assumes that when it dies, all memory will be reclaimed by the kernel.

Specifically, it's pthread (in main) making this assumption (which is a valid assumption on darn near everything found in production written in the last 15+ years). The need to free blocks that still have a valid reference on exit is a bit of a contentious point, but for this specific question all that needs to be mentioned is that the assumption was made.

Edit

It's actually pthread_exit() not cleaning something up on exit, but as explained it probably doesn't need to (or quite possibly can't) once it reaches that point.