Valgrind
Valgrind is a dynamic analysis tool which detects memory errors and memory leaks. It is spiritually the predecessor of modern debugging tools like AddressSanitizer and LeakSanitizer, but remains relevant for debugging applications today because of its thoroughness and ease of setup (no need to recompile applications). They cover similar but not identical usecases [1].
Installation
For better support for Valgrind in system applications, consider enabling valgrind. For example, this will make dev-lang/python detect when Valgrind is in use and switch allocators from its internal pymalloc to valgrind's, giving far better output.
USE flags
USE flags for dev-debug/valgrind An open-source memory debugger for GNU/Linux
mpi
|
Add MPI (Message Passing Interface) layer to the apps that support it |
verify-sig
|
Verify upstream signatures on distfiles |
Emerge
root #
emerge --ask dev-debug/valgrind
Configuration
Environment variables
- VALGRIND_OPTS
Files
- ~/.valgrindrc - Local (per user) configuration file.
- ./.valgrindrc - Local (per project/directory) configuration file.
Usage
Valgrind is actually a suite of tools, but for many people, "Valgrind" is synonymous with the default tool memcheck. The following tools are available, which can be selected with valgrind --tool=name:
- cachegrind (cache and branch-prediction profiler)
- callgrind (call-graph generating cache and branch prediction profiler)
- dhat (dynamic heap analysis tool)
- drd (thread safety analysis)
- helgrind (thread error detector)
- lackey (example tool, can be used to analyze a specific function)
- massif (heap memory profiler)
- memcheck (memory error detector)
Using Valgrind with applications is easy, simply run valgrind /path/to/application. No recompilation is needed!
For example, to run Valgrind on uptime:
user $
valgrind uptime
==3064010== Memcheck, a memory error detector ==3064010== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==3064010== Using Valgrind-3.20.0 and LibVEX; rerun with -h for copyright info ==3064010== Command: uptime ==3064010== 03:35:26 up 4 days, 6:58, 1 user, load average: 0.15, 2.26, 10.93 ==3064010== ==3064010== HEAP SUMMARY: ==3064010== in use at exit: 0 bytes in 0 blocks ==3064010== total heap usage: 57 allocs, 57 frees, 31,824 bytes allocated ==3064010== ==3064010== All heap blocks were freed -- no leaks are possible ==3064010== ==3064010== For lists of detected and suppressed errors, rerun with: -s ==3064010== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
The output states that uptime ran successfully with no detected memory leaks and no memory safety issues (no out-of-bounds access, etc).
Invocation
user $
valgrind --help
Troubleshooting
Valgrind often needs debug information of the C library to perform function redirection. For this, create the package debug environment described above and apply it for sys-libs/glibc (or sys-libs/musl as needed).
First, debugedit should be installed:
root #
emerge --ask dev-util/debugedit
Configure Portage to build selected packages with (enhanced) debugging symbols (-ggdb3
) and not to strip them:
CFLAGS="${CFLAGS} -ggdb3"
CXXFLAGS="${CXXFLAGS} -ggdb3"
FEATURES="${FEATURES} splitdebug compressdebug -nostrip"
FEATURES="${FEATURES} installsources"
Enable these settings for the required software:
sys-libs/glibc debugsyms installsources
Remember to re-emerge the libc after setting the needed package.env variables:
root #
emerge --ask --oneshot sys-libs/glibc
To get meaningful backtraces, users may need to build more packages (such as dependencies of the software being debugged) with the above environment. For local projects, programs should be built with -Og -ggdb3
.
Refuses to launch with strlen error
It is possible that Valgrind refuses to launch with an error like so:
valgrind: A must-be-redirected function valgrind: whose name matches the pattern: strlen valgrind: in an object with soname matching: ld-linux-x86-64.so.2
In this case, add -fno-builtin-strlen
to CFLAGS
for sys-libs/glibc:
# Needed for Valgrind
CFLAGS="${CFLAGS} -fno-builtin-strlen"
sys-libs/glibc glibc-no-strlen
Unhandled instruction bytes
This could be a few different errors and Valgrind's own FAQ covers it. The most common reason for seeing this however is that Valgrind does not currently support AVX512. Users should try building glibc with -march=x86-64-v3 or similar.
Removal
Unmerge
root #
emerge --ask --depclean --verbose dev-debug/valgrind
See also
- GDB — used to investigate runtime errors that normally involve memory corruption
- AddressSanitizer — a compiler feature in GCC and Clang that is able to detect several memory access errors.
- UndefinedBehaviorSanitizer — a compiler feature in GCC and Clang that is able to detect various forms of undefined behaviour (UB).
External resources
- Debug memory errors with Valgrind and GDB
- Valgrind Memcheck: Different ways to lose your memory
- Twenty years of Valgrind
- GDB valgrind integration
- Valgrind and GDB in close cooperation
References
- ↑ Jan Kratochvil. Memory error checking in C and C++: Comparing Sanitizers and Valgrind, Red Hat Developer Blog, May 5th, 2021. Retrieved on January 26th, 2023.