valgrind
is a great tool to assist. One problem we can run into is extra noise from system/non project libraries masking your own issues. Refocussing is relatively straight forward:
https://valgrind.org/docs/manual/manual-core.html#manual-core.suppress
$ valgrind --gen-suppressions=all ./audiotag ../tests/test.mp3
==17943== Invalid read of size 32
==17943== at 0x641D5D9: __wmemcmp_avx2_movbe (in /usr/lib64/libc.so.6)
==17943== by 0x48F1785: TagLib::String::operator<(TagLib::String const&) const (in /usr/lib64/libtag.so.1.18.0)
==17943== by 0x48E533B: ??? (in /usr/lib64/libtag.so.1.18.0)
==17943== by 0x48F7E81: TagLib::PropertyMap::operator[](TagLib::String const&) (in /usr/lib64/libtag.so.1.18.0)
==17943== by 0x492052E: TagLib::Tag::properties() const (in /usr/lib64/libtag.so.1.18.0)
==17943== by 0x40A5FA: _properties (Meta.h:366)
==17943== by 0x40A5FA: AudioTag::MetaMP3::properties(TagLib::Tag const&) const (Meta.cc:473)
==17943== by 0x41041F: AudioTag::MetaOutJson::out(std::ostream&, AudioTag::File const&) (MetaOut.cc:122)
==17943== by 0x410806: execute (Ops.h:32)
==17943== by 0x410806: AudioTag::Ops::execute(AudioTag::File&) const (Ops.cc:23)
==17943== by 0x40779E: main (audiotag.cc:570)
==17943== Address 0xf6ea210 is 0 bytes inside a block of size 28 alloc'd
==17943== at 0x4844FF5: operator new(unsigned long) (vg_replace_malloc.c:422)
==17943== by 0x48E9C79: TagLib::String::upper() const (in /usr/lib64/libtag.so.1.18.0)
==17943== by 0x48F7E69: TagLib::PropertyMap::operator[](TagLib::String const&) (in /usr/lib64/libtag.so.1.18.0)
==17943== by 0x49204DE: TagLib::Tag::properties() const (in /usr/lib64/libtag.so.1.18.0)
==17943== by 0x40A5FA: _properties (Meta.h:366)
==17943== by 0x40A5FA: AudioTag::MetaMP3::properties(TagLib::Tag const&) const (Meta.cc:473)
==17943== by 0x41041F: AudioTag::MetaOutJson::out(std::ostream&, AudioTag::File const&) (MetaOut.cc:122)
==17943== by 0x410806: execute (Ops.h:32)
==17943== by 0x410806: AudioTag::Ops::execute(AudioTag::File&) const (Ops.cc:23)
==17943== by 0x40779E: main (audiotag.cc:570)
==17943==
{
<<>insert_a_suppression_name_here<>>
Memcheck:Addr32
fun:__wmemcmp_avx2_movbe
fun:_ZNK6TagLib6StringltERKS0_
obj:/usr/lib64/libtag.so.1.18.0
fun:_ZN6TagLib11PropertyMapixERKNS_6StringE
fun:_ZNK6TagLib3Tag10propertiesEv
fun:_properties
fun:_ZNK8AudioTag7MetaMP310propertiesERKN6TagLib3TagE
fun:_ZN8AudioTag11MetaOutJson3outERSoRKNS_4FileE
fun:execute
fun:_ZNK8AudioTag3Ops7executeERNS_4FileE
fun:main
}
...
$ cat > valgrind.supress << EOF
{
rule_ignore_system_libs
Memcheck:Leak
obj:*/lib*/lib*.so.*
}
{
rule_ignore_tablib_invalid_read
Memcheck:Addr32
fun:__wmemcmp_avx2_movbe
fun:_ZNK6TagLib6StringltERKS0_
obj:/usr/lib64/libtag.so.*
}
EOF
$ valgrind --suppressions=valgrind.suppress ./audiotag ../tests/test.mp3
With suppressions enabled you should be able to concentrate on items related to your project. However if you need to dig further, there are advanced techniques to help narrowing down your memory issues: using gdb
along with valgrind
is a power combination:You will need two terminals, one starting
valgrind
in paused start and then gdb
in another terminal connecting to the former.
$ valgrind --vgdb-error=0 ./audiotag -d1A -l ../tests/test.mp3
==40385== Memcheck, a memory error detector
==40385== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==40385== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==40385== Command: ./audiotag -d1A -l ../tests/test.mp3
==40385==
==40385== (action at startup) vgdb me ...
==40385==
==40385== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==40385== /path/to/gdb ./audiotag
==40385== and then give GDB the following command
==40385== target remote | /usr/libexec/valgrind/../../bin/vgdb --pid=40385
==40385== --pid is optional if only one valgrind process is running
==40385==
In second terminal:
$ gdb ./audiotag
..
(gdb) target remote | /usr/libexec/valgrind/../../bin/vgdb --pid=40385
(gdb) monitor help
(gdb) monitor leak_check full reachable any
(gdb) br ...
...
(gdb) mo l
==40385== LEAK SUMMARY:
==40385== definitely lost: 0 (+0) bytes in 0 (+0) blocks
==40385== indirectly lost: 0 (+0) bytes in 0 (+0) blocks
==40385== possibly lost: 0 (+0) bytes in 0 (+0) blocks
==40385== still reachable: 299,633 (+0) bytes in 1,109 (+0) blocks
==40385== suppressed: 0 (+0) bytes in 0 (+0) blocks
==40385== Reachable blocks (those to which a pointer was found) are not shown.
==40385== To see them, add 'reachable any' args to leak_check
==40385==
Once connected you can continue adding break points with the monitor
commands evaluating specific execution paths where the memory errors occur.
No comments:
Post a Comment