Is there a way to identify at run-time of an executable is being run from within valgrind? I have a set of C++ unit tests, and one of them expects std::vector::reserve
to throw std::bad_alloc
. When I run this under valgrind, it bails out completely, preventing me from testing for both memory leaks (using valgrind) and behavior (expecting the exception to be thrown).
Here's a minimal example that reproduces it:
#include <vector>
int main()
{
size_t uint_max = static_cast<size_t>(-1);
std::vector<char> v;
v.reserve(uint_max);
}
Running valgrind, I get this output:
Warning: silly arg (-1) to __builtin_new()
new/new[] failed and should throw an exception, but Valgrind
cannot throw exceptions and so is aborting instead. Sorry.
at 0x40192BC: VALGRIND_PRINTF_BACKTRACE (valgrind.h:319)
by 0x401C823: operator new(unsigned) (vg_replace_malloc.c:164)
by 0x80487BF: std::vector<char, std::allocator<char> >::reserve(unsigned) new_allocator.h:92)
by 0x804874D: main (vg.cxx:6)
I'd like to modify my unit test to simply skip the offending code when it's being run from within valgrind. Is this possible?
You should look at this page from the Valgrind manual, it contains a RUNNING_ON_VALGRIND
macro (included from valgrind.h) which does what you want.
If one does not want to include valgrind.h
(which requires an autoconf test or similar) or use a wrapper, here's a heuristic for Linux (and other systems using ELF?): test the value of the LD_PRELOAD
environment variable since Valgrind works by preloading libraries. I use the following test in C to check whether LD_PRELOAD
contains the string "/valgrind/"
or "/vgpreload"
:
int tests_run_within_valgrind (void)
{
char *p = getenv ("LD_PRELOAD");
if (p == NULL)
return 0;
return (strstr (p, "/valgrind/") != NULL ||
strstr (p, "/vgpreload") != NULL);
}
Other systems might have a similar solution. I suggest the following command to see whether the environment mentions Valgrind:
valgrind env | grep -i valgrind
Edit: In the relatively unlikely event that you are trying to do this either on macOS or on FreeBSD i386 running on an amd64 kernel then the environment variables are different.
Plain LD_PRELOAD should work for all Linux and Solaris variants.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With