We use valgrind as a part of our CI process. If there are some memory problems, valgrind must return non-zero code, and this incident is reported. This is how we run it:
valgrind --error-exitcode=1 --tool=memcheck --leak-check=full \
--errors-for-leak-kinds=definite --show-leak-kinds=definite \
--track-origins=yes ./some_cgo_application
(...)
==25182== HEAP SUMMARY:
==25182== in use at exit: 2,416,970 bytes in 34,296 blocks
==25182== total heap usage: 83,979 allocs, 49,684 frees, 5,168,335 bytes allocated
==25182==
==25182== LEAK SUMMARY:
==25182== definitely lost: 0 bytes in 0 blocks
==25182== indirectly lost: 0 bytes in 0 blocks
==25182== possibly lost: 3,024 bytes in 7 blocks
==25182== still reachable: 2,413,946 bytes in 34,289 blocks
==25182== of which reachable via heuristic:
==25182== newarray : 520 bytes in 1 blocks
==25182== suppressed: 0 bytes in 0 blocks
==25182== Reachable blocks (those to which a pointer was found) are not shown.
==25182== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==25182==
==25182== For counts of detected and suppressed errors, rerun with: -v
==25182== ERROR SUMMARY: 20 errors from 5 contexts (suppressed: 0 from 0)
Currently we're interested only in memory that is definitly lost. If no blocks are definitly lost, valgrind's exit code is expected to be zero. However, it returns 1 despite of the options --errors-for-leak-kinds=definite --show-leak-kinds=definite.
echo $?
1
Are thery any other options that will help to achieve the desired result?
I suspect the exit status 1 comes from the program itself. I can reproduce this with:
$ valgrind --error-exitcode=1 --tool=memcheck --leak-check=full \
--errors-for-leak-kinds=definite --show-leak-kinds=definite \
--track-origins=yes /bin/false
This does not look like something that can be changed in the current sources:
case VgSrc_ExitProcess: /* the normal way out (Darwin) */
/* Change the application return code to user's return code,
if an error was found */
if (VG_(clo_error_exitcode) > 0
&& VG_(get_n_errs_found)() > 0) {
VG_(client_exit)( VG_(clo_error_exitcode) );
} else {
/* otherwise, return the client's exit code, in the normal
way. */
VG_(client_exit)( VG_(threads)[tid].os_state.exitcode );
}
And this exitcode member is set from the sys_exit_group wrapper in coregrind/m_syswrap/syswrap-linux.c, without any way to tweak it.
Considering this, I think your best bet (without patching valgrind) is to select an exit status different from any exit status your program might use, and use that as an indicator of a valgrind error.
Have a look at the --gen-suppressions option. With this you can create a file that tells valgrind to suppress call-stack-specific possibly lost and still reachable errors. Using this file, re run valgrind with --supressions=filename. Now the return value of valgrind ($?) will be zero. Here's an example:
valgrind --gen-suppressions=auto --log-file=suppressions.supp ./path/to/program
<open suppressions.supp, delete all lines that are not suppressions, save, and close>
valgrind --suppressions=suppressions.supp ./path/to/program
echo $?
You should see zero printed.
This won't future proof your code for new possibly lost and still reachable errors, but it will remove current errors. If you want to future proof your code you could write a script that parses the output of --gen-suppressions=auto and generates a new suppressions file. The script can be made so that it only adds suppressions for possibly lost and still reachable errors, so you would still see the errors you care about.
Related
ALL,
igor#IgorReinCloud ~/dbhandler/Debug/dbhandler $ valgrind --demangle=yes dbhandler --log-file=memcheck.log --leak-check=full
==28275== Memcheck, a memory error detector
==28275== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==28275== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==28275== Command: dbhandler --log-file=memcheck.log --leak-check=full
// Some errors logged on screen
Unknown long option 'log-file'
// Some more errors logged on screen
Usage: dbhandler [-h] [--verbose]
-h, --help show this help message
--verbose generate verbose log messages
==28275==
==28275== HEAP SUMMARY:
==28275== in use at exit: 1,549,966 bytes in 16,372 blocks
==28275== total heap usage: 177,899 allocs, 161,527 frees,
10,849,729 bytes allocated
==28275==
==28275== LEAK SUMMARY:
==28275== definitely lost: 0 bytes in 0 blocks
==28275== indirectly lost: 0 bytes in 0 blocks
==28275== possibly lost: 3,408 bytes in 32 blocks
==28275== still reachable: 1,464,270 bytes in 15,670 blocks
==28275== of which reachable via heuristic:
==28275== length64 : 4,872 bytes in 81 blocks
==28275== newarray : 2,096 bytes in 51 blocks
==28275== suppressed: 0 bytes in 0 blocks
==28275== Rerun with --leak-check=full to see details of leaked memory
==28275==
==28275== For counts of detected and suppressed errors, rerun with: -v
==28275== Use --track-origins=yes to see where uninitialised values come from
==28275== ERROR SUMMARY: 28 errors from 8 contexts (suppressed: 0 from 0)
However,
igor#IgorReinCloud ~/dbhandler/Debug/dbhandler $ valgrind --help | grep log
--time-stamp=no|yes add timestamps to log messages? [no]
--log-fd=<number> log messages to file descriptor [2=stderr]
--log-file=<file> log messages to <file>
--log-socket=ipaddr:port log messages to socket ipaddr:port
igor#IgorReinCloud ~/dbhandler/Debug/dbhandler $
So what the problem is? Why the messages are not going to the log file as it should? Am I missing an option here?
TIA!
Put the options to Valgrind before the program you want it to check. It assumes options after the program name are options to the program, not Valgrind.
Hence, you have:
valgrind --demangle=yes dbhandler --log-file=memcheck.log --leak-check=full
but you should be using:
valgrind --demangle=yes --log-file=memcheck.log --leak-check=full dbhandler
or even use -- to state that you've finished the options to Valgrind:
valgrind --demangle=yes --log-file=memcheck.log --leak-check=full -- dbhandler
The Unknown long option log-file message probably comes from dbhandler and not Valgrind. It's also why you're getting the 'usage' message from dbhandler.
I'm learning Rust and I was playing with Box, so I tried checking leaks with valgrind but it shows that there are no allocations on the heap:
$ rustc -C opt-level=0 raii.rs
$ valgrind ./raii
==3850== Memcheck, a memory error detector
==3850== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==3850== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==3850== Command: ./raii
==3850==
5
Changed:10
==3850==
==3850== HEAP SUMMARY:
==3850== in use at exit: 0 bytes in 0 blocks
==3850== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==3850==
==3850== All heap blocks were freed -- no leaks are possible
==3850==
==3850== For counts of detected and suppressed errors, rerun with: -v
==3850== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
valgrind --leak-check=full ./raii shows exaclty the same result.
Here's the Rust code:
fn main() {
let mut _box2 = Box::new(5i32);
println!("{}", _box2);
*_box2 = 10i32;
println!("Changed:{}", _box2);
{
let _box3 = Box::new(4i32);
}
}
Some other info:
$ rustc -V
rustc 1.8.0 (db2939409 2016-04-11)
$ valgrind --version
valgrind-3.10.1
$ uname -a
Linux 3.19.0-59-generic #65~14.04.1-Ubuntu SMP Tue Apr 19 18:57:09 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Why is that? I thought Box allocates the variable on the heap. Also, this example shows almost the same code and Valgrind shows allocations there.
If I add the following code:
let _stack = (1u64, 2u64, 3u64);
let _heap = Box::new((4u64, 5u64, 6u64));
println!("Memory used by stack: {} bytes", std::mem::size_of_val(&_stack));
println!("Memory used by heap: {} bytes", std::mem::size_of_val(&_heap));
It prints exactly what I expected:
$ ./raii
Memory used by stack: 24 bytes
Memory used by heap: 8 bytes
In the second case, the tuple was placed on the heap and a pointer (8 bytes) was pushed to the stack.
In the first case tuple was placed on the stack, so it takes 24 bytes.
Valgrind seems to be able to count heap allocations from other programs:
$ valgrind echo "test"
==4575== Memcheck, a memory error detector
==4575== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4575== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==4575== Command: echo test
==4575==
test
==4575==
==4575== HEAP SUMMARY:
==4575== in use at exit: 0 bytes in 0 blocks
==4575== total heap usage: 30 allocs, 30 frees, 3,681 bytes allocated
==4575==
==4575== All heap blocks were freed -- no leaks are possible
==4575==
==4575== For counts of detected and suppressed errors, rerun with: -v
==4575== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Rust 1.32
As of Rust 1.32, the default allocator for an executable is now the system allocator, so you don't need to set anything by default.
Previous versions
Rust uses jemalloc as the allocator when you build a binary. The way that jemalloc is currently compiled does not contain the Valgrind hooks needed.
If you need the ability to track allocations with Valgrind, you can switch to the the system allocator if you are using nightly Rust.
See also:
Why does Valgrind not detect a memory leak in a Rust program using nightly 1.29.0?
I am using valgrind on a program which runs an infinite loop.
As memcheck displays the memory leaks after the end of the program, but as my program has infinite loop it will never end.
So is there any way i can forcefully dump the data from valgrind time to time.
Thanks
Have a look at the client requests feature of memcheck. You can probably use VALGRIND_DO_LEAK_CHECK or similar.
EDIT:
In response to the statement above that this doesn't work. Here is an example program which loops forever:
#include <valgrind/memcheck.h>
#include <unistd.h>
#include <cstdlib>
int main(int argc, char* argv[])
{
while(true) {
char* leaked = new char[1];
VALGRIND_DO_LEAK_CHECK;
sleep(1);
}
return EXIT_SUCCESS;
}
When I run this in valgrind, I get an endless output of new leaks:
$ valgrind ./a.out
==16082== Memcheck, a memory error detector
==16082== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==16082== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==16082== Command: ./a.out
==16082==
==16082== LEAK SUMMARY:
==16082== definitely lost: 0 bytes in 0 blocks
==16082== indirectly lost: 0 bytes in 0 blocks
==16082== possibly lost: 0 bytes in 0 blocks
==16082== still reachable: 1 bytes in 1 blocks
==16082== suppressed: 0 bytes in 0 blocks
==16082== Reachable blocks (those to which a pointer was found) are not shown.
==16082== To see them, rerun with: --leak-check=full --show-reachable=yes
==16082==
==16082== 1 bytes in 1 blocks are definitely lost in loss record 2 of 2
==16082== at 0x4C2BF77: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16082== by 0x4007EE: main (testme.cc:9)
==16082==
==16082== LEAK SUMMARY:
==16082== definitely lost: 1 bytes in 1 blocks
==16082== indirectly lost: 0 bytes in 0 blocks
==16082== possibly lost: 0 bytes in 0 blocks
==16082== still reachable: 1 bytes in 1 blocks
==16082== suppressed: 0 bytes in 0 blocks
==16082== Reachable blocks (those to which a pointer was found) are not shown.
==16082== To see them, rerun with: --leak-check=full --show-reachable=yes
==16082==
==16082== 2 bytes in 2 blocks are definitely lost in loss record 2 of 2
==16082== at 0x4C2BF77: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16082== by 0x4007EE: main (testme.cc:9)
==16082==
==16082== LEAK SUMMARY:
==16082== definitely lost: 2 bytes in 2 blocks
==16082== indirectly lost: 0 bytes in 0 blocks
==16082== possibly lost: 0 bytes in 0 blocks
==16082== still reachable: 1 bytes in 1 blocks
==16082== suppressed: 0 bytes in 0 blocks
==16082== Reachable blocks (those to which a pointer was found) are not shown.
==16082== To see them, rerun with: --leak-check=full --show-reachable=yes
The program does not terminate.
with valgrind 3.7.0, you can trigger (a.o.) leak search from the shell,
using vgdb.
See e.g. http://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.monitor-commands
(you can do these monitor commands from gdb or from a shell command line, using vgdb).
Use of VALGRIND_DO_LEAK_CHECK (acm answer) works for me.
Remarks :
- Program has to be launch with valgrind (valgrind myProg ...)
- valgrind-devel package has to be installed (to have )
I am trying to understand whether or not my application is leaking.
When running my application, I periodically run pmap and observe:
mapped: 488256K writeable/private: 90144K shared: 0K
mapped: 488260K writeable/private: 101912K shared: 0K
mapped: 488256K writeable/private: 102708K shared: 0K
mapped: 488260K writeable/private: 105112K shared: 0K
I run top and observe:
VIRT RES SHR
488260 17684 3020
488256 20060 3032
488256 22700 3032
488256 26132 3032
488256 28772 3032
488256 31880 3032
The increase in "RES" and in "writeable/private" is what makes me suspect a leak. However, running valgrind I do not detect any major leak, and when I abort execution I consistently
see about 20Mb reachable memory:
==19998==
==19998== HEAP SUMMARY:
==19998== in use at exit: 20,351,513 bytes in 974 blocks
==19998== total heap usage: 329,404 allocs, 328,430 frees, 34,562,346 bytes allocated
==19998==
==19998== LEAK SUMMARY:
==19998== definitely lost: 63 bytes in 4 blocks
==19998== indirectly lost: 0 bytes in 0 blocks
==19998== possibly lost: 4,679 bytes in 76 blocks
==19998== still reachable: 20,346,771 bytes in 894 blocks
==19998== suppressed: 0 bytes in 0 blocks
==19998== Rerun with --leak-check=full to see details of leaked memory
==19998==
==19998== For counts of detected and suppressed errors, rerun with: -v
==19998== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
I run valgrind --tool=massif and also see 20Mb flat:
QUESTION: Can someone please explain why valgrind and massif tell me that my program uses 20Mb memory consistently, but top and pmap tell me usage is growing?
In order to understand why top shows increase for your process you also need to analyze memory allocations in your program with valgrind --pages-as-heap=yes. You will understand why there is increase. It is the way top measures memory consumption of a process. http://valgrind.org/docs/manual/ms-manual.html#ms-manual.not-measured. And with valgrind --pages-as-heap=yes you will see where these allocations are done in you program
Currently I manage a module of my lab.
I checked for memory leaks using valgrind. I found several memory leaks and fixed them. And when I made a '.so' file to provide the module as a library and test code for running the '.so' library, valgrind reports a memory leak that did not exist in the original program.
There is no missing function in the test code. I think that the difference of options when compiling with g++ cause this situation. But I couldn't verify this.
I use the options below to compile the original module
-ggdb -I. -D_DEBUG -D_CICODE -D_EDITMODE -DPOINTER -fPIC
and
-shared -W1,-soname,libmysutff.so.1
to make the .so file.
Working environment: Ubuntu 10.10, g++
This is the output of valgrind:
==23426==
==23426== HEAP SUMMARY:
==23426== in use at exit: 1,148 bytes in 8 blocks
==23426== total heap usage: 4,294 allocs, 4,286 frees, 43,176,780 bytes allocated
==23426==
==23426== 300 bytes in 1 blocks are definitely lost in loss record 5 of 6
==23426== at 0x4C2815C: malloc (vg_replace_malloc.c:236)
==23426== by 0x400A27: main
==23426==
==23426== 848 (120 direct, 728 indirect) bytes in 1 blocks are definitely lost in loss record 6 of 6
==23426== at 0x4C27480: calloc (vg_replace_malloc.c:467)
==23426== by 0x4E6E6B6: NewPathNode() (mem_manager.cpp:156)
==23426== by 0x4E61F21: Morph_No_Space(unsigned char*, _path_node**, int, unsigned char) (API.cpp:198)
==23426== by 0x4E625F6: API_Morph (API.cpp:350)
==23426== by 0x4E626A0: API_Tagger (API.cpp:379)
==23426== by 0x400ADC: main
==23426==
==23426== LEAK SUMMARY:
==23426== definitely lost: 420 bytes in 2 blocks
==23426== indirectly lost: 728 bytes in 6 blocks
==23426== possibly lost: 0 bytes in 0 blocks
==23426== still reachable: 0 bytes in 0 blocks
==23426== suppressed: 0 bytes in 0 blocks
==23426==
==23426== For counts of detected and suppressed errors, rerun with: -v
==23426== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 4 from 4)