Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

255
Views
How to trigger erroneous code paths for tests in C?

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?

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

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.

over 4 years ago · Santiago Trujillo Report

0

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.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!