简体   繁体   中英

GCC Makefile Define

I have some C code that I want to do some tests on. It uses malloc, calloc, and free through out the code. I want to change those functions to a custom function that internally calls the original function. For example:

emxArray->size = (int *)malloc((unsigned int)(sizeof(int) * numDimensions));

would become:

emxArray->size = (int *)myMalloc((unsigned int)(sizeof(int) * numDimensions));

where myMalloc is:

void* myMalloc(unsigned size)
{
    if (size < 8)
    {
        //printf("*** Bumped from %d....\n", size);
        size = 8;
    }
    allocated += size;
    return malloc(size);
}

As you can see, myMalloc internally calls malloc. It just does some extra stuff. I wanted to replace the usage of malloc through out the code with myMalloc. I have done this successfully by going through all the code and replacing malloc with myMalloc manually, but this is far from ideal. I will be replacing this code on a test only basis, thus the production code should contain only malloc calls. I realize I could also do this with a script, but wanted to just use a define statement in the Makefile:

-Dmalloc=myMalloc

But that also replaces malloc in the myMalloc function, which causes an infinite recursive situation. I tried changing the malloc call in the myMalloc function to malloc_d, and added a second define to the Makefile.

-Dmalloc=myMalloc -Dmalloc_d=malloc

I was thinking that the first define would not replace the malloc_d (which it didn't) and that the second define would only change the malloc_d (which it didn't). I got the same recursive situation. Is there anyway to do this with Makefile defines? Or are multipass pre-compile situations going to always mess this up?

UPDATE:

Ok, so I have started looking at the LD_PRELOAD option that has been pointed out. I thought I had a workable solution, however, I am still having trouble! Here is what I did...

  1. I moved myMalloc() and myFree() out of the main file and into its own file. I then compiled it into a shared library using: gcc -shared -o libMyMalloc.so -fPIC myMalloc.c
  2. I then added the following 'dummy functions' to the main file:

    void* myMalloc(unsigned size) { void* ptr; return ptr; }

    void myFree(void* ptr) { }

As you can see, they do nothing.

  1. I added the following defines to the make file: -Dmalloc=myMalloc \\ -Dfree=myFree
  2. I compiled the code and ran it against the libMyMalloc.so library I created:

    LD_PRELOAD=/home/rad/Desktop/myMalloc/libMyMalloc.so ./testRegress

However, I am still not getting it to run with the myMalloc functions that are defined in the libMyMalloc.so file.

The simplest solution is to not call malloc directly in your code: If you choose a different name (say MALLOC ), it's trivial to switch to a custom allocator.

Example code:

#ifndef MALLOC
#define MALLOC malloc
#endif

For test builds, you'd do -DMALLOC=myMalloc .

It gets more complicated if for some reason you want keep the calls to malloc . Then you'd have to add something like the following after all standard library headers have been included :

#ifdef USE_MY_MALLOC
#undef malloc
#define malloc(SIZE) myMalloc(SIZE)
#endif

You can call the standard library function by using parens, ie

void* myMalloc(unsigned size)
{
    ...
    return (malloc)(size);
}

and enable it via -DUSE_MY_MALLOC .


Considering the additional requirements given in the comments, two approaches come to mind:

  • pre-process the generated source, textually replacing calls to malloc
  • intercept inclusion of stdlib.h (assuming that's where MATLAB gets its malloc declaration from)

Your own version of stdlib.h would look something like this:

#ifndef MY_STDLIB_H_
#define MY_STDLIB_H_

#include "/usr/include/stdlib.h"

#undef malloc
#define malloc(SIZE) myMalloc(SIZE)

#endif

Then, you can conditionally add the directory where you've placed that file to the include path. Also note that this is not a particularly robust solution, but it might work for you anyway.

You can use a pointer to a function. In the normal case, make it point to malloc. In debugging mode, let it point to you function.

In some h file:

extern void *(*myMalloc)(size_t size);

In one of you c files:

#ifdef DEBUG
void *(*myMalloc)(size_t size) = dMalloc;
#else
void *(*myMalloc)(size_t size) = malloc; // derived from libc
#endif

I found my solution and wanted to share. Thank you to everyone that contributed and pointed me in the right direction.

I ended up creating my custom library code and compiling it into a shared library:

gcc -shared -o libtmalloc.so -fPIC tmalloc.c

I then modified the makefile to use the shared library and globally define 'malloc' to my custom function name (which internally calls malloc()) to malloc_t, as well as calloc() and free():

gcc -L/home/path/to/mallocTrace -Wall -o test test.c lib/coder/*.c -lm -ltmalloc \
-Dmalloc=malloc_t \
-Dcalloc=calloc_t \
-Dfree=free_t

The defines changed all the function calls for me which were linked to the implementation in the shared library. Because I am using a shared library (which is already compiled), I didn't have to worry about my makefile defines causing a recursive call situation in my custom functions. With this usage, I can take any pre-generated C code from my other tools and observe the memory usage with these simple makefile changes and using my custom malloc trace library.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM