2

I want to mock functions of the c lib such as malloc without altering too much the original source file (the one that uses malloc).

I tried including a header file "mock.h" like

#ifndef MOCK_H_
# define MOCK_H_
# ifdef MOCK_MODE

#  include <sys/types.h>

extern void *my_mock_malloc(size_t n);
void    *malloc(size_t n) __attribute__((weak, alias ("my_mock_malloc")));

# endif /* MOCK_MODE */
#endif /* !MOCK_H_ */

but it gives me an error

in file included from ...:
/usr/include/stdlib.h:466:14: error: ‘malloc’ aliased to undefined symbol ‘my_mock_malloc’
 extern void *malloc (size_t __size) __THROW __attribute_malloc__ __wur;

GCC alias to function outside of translation unit -AKA- is this even the right tool for the job? gives a partial solution: using the linker I create an alias on a symbol. I can now compile with -Xlinker --defsym "malloc"="my_mock_malloc". The problem is that all my .o files are linked using this option and thus the unit testing framework I use (check) is affected by the mocking (and thus it receives is SIGSEGV when I make my mock function return NULL).

Is there a way to perform such symbol aliasing locally, so I can make my tesing framework use the real malloc? Os is there a better solution than this one?

Community
  • 1
  • 1
Thüzhen
  • 183
  • 6

4 Answers4

3

Most implementations of the C language specify all symbols of the libc as weak, that is, you can override them as needed. Try it out! You can write your own function named malloc and it automatically replaces the library supplied malloc. Have a look at your platforms documentation as there are a couple more functions (like free, realloc, calloc, etc) that you need to implement for a malloc replacement to be complete.

fuz
  • 88,405
  • 25
  • 200
  • 352
  • I tried removing the `#define` from my answer here, and renaming the function to `malloc`. It compiled cleanly but hung. – Weather Vane Apr 23 '15 at 13:21
  • Did you implement all other needed functions, too? What platform are you working on? – fuz Apr 23 '15 at 15:42
  • You'll see in my answer what I did. `my_malloc` prints a message saying it was called, and returns `NULL`. There are no other needed functions in that example. When I removed the `#include ` and the `#define` and renamed the function to `malloc` it compiled but did not run - hung. MSVC 2009. – Weather Vane Apr 23 '15 at 15:46
  • That's because GNU printf calls malloc internally! You get an infimite loop. And again, you must override the other functions, too or weirf behaviour occurs. – fuz Apr 23 '15 at 16:21
  • Ahhhhh I only really tested `#define` for local use. But I wonder then why `printf` worked in my original answer (and Gme is Gnot Gnu) -;) – Weather Vane Apr 23 '15 at 16:43
2

I found a solution which is to include a header file mock.h like

#ifndef MOCK_H_
# define MOCK_H_
# ifdef MOCK_MODE

#  include <sys/types.h>

extern void *my_mock_malloc(size_t n);
#  define malloc(x) (my_mock_malloc(x))

# endif /* MOCK_MODE */
#endif /* !MOCK_H_ */

but I am still curious about another solution.

Thüzhen
  • 183
  • 6
0

You could do it like this:

#include <stdio.h>
#include <stdlib.h>

#define malloc my_malloc

void *my_malloc(size_t size) {
    printf ("Called my_malloc\n");
    return NULL;
}

int main(void) {
    char * array = malloc(100);
    return 0;
}

Program output:

Called my_malloc
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
0

Although not a full answer to your question, you will find that CppUTest is very useful for testing C code as well, and includes most of the malloc/free library in its mock capabilities, allowing you to control malloc failure and so on. It's also very good for debugging memory allocation issues since it uses a debug allocator.

I found that the framework documentation was however a little lacking in detail and examples.

When I used that framework "in anger" a couple of years ago, I found it necessary to implement my own mocked strdup() function, which I did within the CppUTest source.

https://cpputest.github.io/mocking_manual.html

I added the DeathHandler facility as well, to help capture and diagnose segfaults during test.

MikeW
  • 5,504
  • 1
  • 34
  • 29