Alternative to Valgrind (Memcheck) for Finding Leaks on Linux

How to check for memory leaks in a large scale c++ Linux application?

First of all...

and we reached the point when it is mandatory to make a roundup of checks for memory leaks.

This, actually, is a problem of methodology. Correctness should be the primary goal of any software piece and not an afterthought.

I will suppose though that you now realize this and how much easier it would have been to identify the problems had you been running an instrumented unit test at each commit.


So, what to do now ?

  • Runtime detection:

    • Try to make Valgrind work, you probably have some environmental issues
    • Try ASan, ThreadSan and MemSan; they are not trivial to setup under Linux but oh so impressive!
    • Try instrumented builds: tcmalloc includes a heap-checker for example
    • ...
  • Compile time detection:

    • Turn on the warnings (preferably with -Werror) (not specific to your issue)
    • Use static analysis, such as Clang's, it may spot unpaired allocation routines
    • ...
  • Human detection:

    • Code reviews: make sure all resources are allocated within RAII classes
    • ...

Note: using only RAII classes helps removing memory leaks, but does not help with dangling references. Thankfully, detecting dangling references is what ASan does.


And once you have patched all the issues, make sure that this becomes part of the process. Changes should be reviewed and tested, always, so that rotten eggs are culled immediately rather than left to stink up the code base.

Lightweight memory leak debugging on linux

Surprisingly, I was unable to find anything like Microsoft's UMDH in open-source domain or available for immediate download. (I also looked at Google Heap Leak Checker but it is more like Valgrind rather than to UMDH). So I ended up writing the tool myself using malloc instrumentation project as a reference point:

https://github.com/glagolig/heapwatch

The tool has number of limitations, but it worked just fine for my purposes.

Is there a good Valgrind substitute for Windows?

Some more good commercial tools:

  • Purify
  • Insure++

How I can detect memory leaks of C++ application in Linux (Ubuntu OS)?

Check out Valgrind, it should be in the Ubuntu repository. it can give you detailed information about memory usage in C++ programs. Kind of like a debugger for memory usage.

valgrind --tool=memcheck <your_app> <your_apps_params>

How to use thrust and valgrind together to detect memory leaks?

Currently I am using this suppression file .valgrind-supressions at the root of my project:

{
<suppression_for_thrust_allocations>
Memcheck:Leak
match-leak-kinds: possible
fun:*alloc
...
obj:*libcuda.so.*
...
obj:*libcuda.so.*
fun:__cudart*
...
fun:__cudart*
fun:cudaMalloc
fun:_ZN6thrust6system4cuda6detail20cuda_memory_resourceIXadL_Z10cudaMallocEEXadL_Z8cudaFreeEENS_8cuda_cub7pointerIvEEE11do_allocateEmm
...
}

(the three dots are actual code)

By removing the _ZN6thrust line maybe it could be more general, but I don't want to generalize suppressions prematurely.

It is important to note that this is not checking for leaks in the GPU, for that cuda-memcheck is needed.


UPDATE: I broadened the suppression to 1) include cases generated from cudaMallocManaged as well 2) Caused by CUDA runtime without the participation of thrust allocators (as @RobertCrovella mentioned).

{
<suppression_for_cudaMalloc_and_cudaMallocManaged_allocations>
Memcheck:Leak
match-leak-kinds: possible
fun:*alloc
...
obj:*libcuda.so.*
...
obj:*libcuda.so.*
fun:__cudart*
...
fun:__cudart*
fun:cudaMalloc*
...
}

In CMakeLists.txt I am using these options to actually use the suppression file listed above

  ...
set(MEMORYCHECK_COMMAND_OPTIONS "-q --tool=memcheck --leak-check=yes --num-callers=52 --trace-children=yes --leak-check=full --track-origins=yes --gen-suppressions=all") # must go before `include(CTest)`
set(MEMORYCHECK_SUPPRESSIONS_FILE "${PROJECT_SOURCE_DIR}/.valgrind-suppressions") # must go before `include(CTest)`

include(CTest)
...

(the three dots here stand for the rest of the file)

Improvements to this suppression pattern are welcome.


For reference a full automatically generated suppression by valgrind looks like this:

{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: possible
fun:calloc
obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
fun:__cudart764
fun:__cudart763
fun:__cudart768
fun:__cudart941
fun:__cudart607
fun:cudaMalloc
fun:_ZN6thrust6system4cuda6detail20cuda_memory_resourceIXadL_Z10cudaMallocEEXadL_Z8cudaFreeEENS_8cuda_cub7pointerIvEEE11do_allocateEmm
fun:_ZN6thrust26device_ptr_memory_resourceINS_6system4cuda6detail20cuda_memory_resourceIXadL_Z10cudaMallocEEXadL_Z8cudaFreeEENS_8cuda_cub7pointerIvEEEEE11do_allocateEmm
fun:_ZN6thrust2mr9allocatorIiNS_26device_ptr_memory_resourceINS_6system4cuda6detail20cuda_memory_resourceIXadL_Z10cudaMallocEEXadL_Z8cudaFreeEENS_8cuda_cub7pointerIvEEEEEEE8allocateEm
fun:_ZZN6thrust6detail16allocator_traitsINS_16device_allocatorIiEEE8allocateERS3_mEN19workaround_warnings8allocateES5_m
fun:_ZN6thrust6detail16allocator_traitsINS_16device_allocatorIiEEE8allocateERS3_m
fun:_ZN6thrust6detail18contiguous_storageIiNS_16device_allocatorIiEEE8allocateEm
fun:_ZN6thrust6detail11vector_baseIiNS_16device_allocatorIiEEE17allocate_and_copyINS0_15normal_iteratorIPKiEEEEvmT_SA_RNS0_18contiguous_storageIiS3_EE
fun:_ZN6thrust6detail11vector_baseIiNS_16device_allocatorIiEEE10range_initINS0_15normal_iteratorIPKiEEEEvT_SA_NS_27random_access_traversal_tagE
fun:_ZN6thrust6detail11vector_baseIiNS_16device_allocatorIiEEE10range_initINS0_15normal_iteratorIPKiEEEEvT_SA_
fun:_ZN6thrust6detail11vector_baseIiNS_16device_allocatorIiEEEC1IiSaIiEEERKNS1_IT_T0_EE
fun:_ZN6thrust13device_vectorIiNS_16device_allocatorIiEEEC1IiSaIiEEERKNS_11host_vectorIT_T0_EE
fun:_ZN6vector11test_methodEv
fun:_ZL14vector_invokerv
fun:_ZN5boost6detail8function22void_function_invoker0IPFvvEvE6invokeERNS1_15function_bufferE
obj:/usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.74.0
fun:_ZN5boost17execution_monitor13catch_signalsERKNS_8functionIFivEEE
fun:_ZN5boost17execution_monitor7executeERKNS_8functionIFivEEE
fun:_ZN5boost17execution_monitor8vexecuteERKNS_8functionIFvvEEE
fun:_ZN5boost9unit_test19unit_test_monitor_t21execute_and_translateERKNS_8functionIFvvEEEm
obj:/usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.74.0
obj:/usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.74.0
fun:_ZN5boost9unit_test9framework3runEmb
fun:_ZN5boost9unit_test14unit_test_mainEPFbvEiPPc
fun:main
}


Related Topics



Leave a reply



Submit