I very often write tests to my programs to make sure they work 100% of the time under any circumstances (so that later I don't have to spend hours debugging them).
However, all my tests so far were only testing the lines of code that I can reach under normal circumstances, so for instance I did not test what would happen if malloc()
failed. I really want to do that too though, so recently I began experimenting and seeking answers about how to override any function so that it returns any predefined value and possibly sets errno to some value.
I learned about dlsym, LD_PRELOAD, and --wrap
for linker. So far, I've had many successes with dlsym, even overriding malloc()
and it wouldn't fall into an infinite loop, however Valgrind that I'm using to find memory leaks seems to happily ignore any functions I wrap with dlsym and so for instance malloc()
starts acting normally when I don't want it to under Valgrind (and so returning NULL
artificially doesn't work).
LD_PRELOAD is pretty much used in conjunction with dlsym, it doesn't really do anything on its own.
--wrap
is nice and all, but its flaw is that you need to know the functions you want to override for every file. That is tiresome - with dlsym I can choose the functions in my code and that's it, but --wrap
will make my Makefile significantly more complicated.
I've also tried using libc's hidden definitions (__libc_malloc()
, __libc_function_name()
in general) to override the weak symbols of malloc()
, strxxx()
and other functions that Valgrind likes to override and then using dlsym for everything else, kind of like so:
void* __libc_malloc(size_t);
void* malloc(size_t size) {
if(malloc_fail) {
errno = ENOMEM;
return NULL;
}
return __libc_malloc(size);
}
But then again, Valgrind would happily override this malloc implementation as well and leave me with no options at all.
I've also tried switching my memory leak detector to something like libasan (gcc -fsanitize=address
), but unfortunately I have a very terrible experience with any sanitizers that come with gcc, because of their buggy implementation that for instance crashes when using pthread_cancel()
(like here), and turns out my code needs to test some pthread functions awell, because I am wrapping them in my own functions and structures and stuff.
Is there any other way to trigger erroneous code paths? Am I doing something wrong?
CodePudding user response:
Valgrind provides its own wrappers for malloc
, calloc
, and free
, and this is essential to its operation. I do not find it at all surprising that these displace any wrappers that you try to specify for those functions. The main alternative would be the reverse: your wrappers displacing valgrind's.
I suggest simply segregating your tests into those that depend on you injecting your wrappers and those that don't. Use Valgrind only with tests from the latter group.
CodePudding user response:
The way to do this would be to call your functions something other than malloc
etc. (like my_malloc
).
And if you do that and you still want Valgrind to analyze the memory returned by my_malloc
you will need to use the Valgrind client mechanism to tell Valgrind about your memory pool, allocations etc.
Take a look at this article for an example.