12

I am trying to override malloc by doing this.

#define malloc(X) my_malloc((X))

void* my_malloc(size_t size)
{

    void *p = malloc(size);
    printf ("Allocated = %s, %s, %s, %x\n",__FILE__, __LINE__, __FUNCTION__, p);
    return p;
}

However, this is indefinitely calling my_malloc recursively (because of malloc call inside my_malloc). I wanted to call C malloc function inside my_malloc and not the macro implementation. Could you please let me know how to do that?

Thanks.

Aiden Bell
  • 28,212
  • 4
  • 75
  • 119
  • 1
    Maybe should change title into something more specific. The problem has really nothing to do with malloc or overriding, but rather with preprocessor macros and accessing the original name. – David Rodríguez - dribeas Jul 07 '09 at 20:20
  • 4
    This won't work the way you want it to: `__FILE__`, `__LINE__` and `__FUNCTION__` (C99 syntax would be `__func__`) will always expand to the same value according to their placement in the file containing `my_malloc()`; you have to put them in your macro definition and pass them to `my_malloc()` as arguments! – Christoph Jul 07 '09 at 20:55

9 Answers9

22

Problem solved:

void* my_malloc(size_t size, const char *file, int line, const char *func)
{

    void *p = malloc(size);
    printf ("Allocated = %s, %i, %s, %p[%li]\n", file, line, func, p, size);
    return p;
}
#define malloc(X) my_malloc( X, __FILE__, __LINE__, __FUNCTION__)
pentaphobe
  • 337
  • 1
  • 4
  • 9
Dave Gamble
  • 4,146
  • 23
  • 28
  • 1
    +1 for making my solution appear when I pressed Load New Answers. :) Explanation is that a #define only takes effect for code that appears AFTER it is invoked. – Nick Lewis Jul 07 '09 at 20:07
  • The problem with this (and why it may _not_ be solved), is it only works if you aren't considering existing libraries which are already compiled and calling malloc (which your own code may be responsible to manage). In that case you can do something like this: http://stackoverflow.com/questions/6083337/overriding-malloc-using-the-ld-preload-mechanism – ideasman42 Jun 07 '14 at 00:55
15

With Glibc, there exists malloc_hook(3) as the proper way to globally interpose your own malloc function.

#include <stdio.h>
#include <malloc.h>

static void *(*old_malloc_hook)(size_t, const void *);

static void *new_malloc_hook(size_t size, const void *caller) {
    void *mem;

    __malloc_hook = old_malloc_hook;
    mem = malloc(size);
    fprintf(stderr, "%p: malloc(%zu) = %p\n", caller, size, mem);
    __malloc_hook = new_malloc_hook;

    return mem;
}

static void init_my_hooks(void) {
    old_malloc_hook = __malloc_hook;
    __malloc_hook = new_malloc_hook;
}

void (*__malloc_initialize_hook)(void) = init_my_hooks;
$ cat >mem.c <<'EOF'
(the code above)
EOF
$ cat >main.c <<'EOF'
#include <stdio.h>
#include <stdlib.h>
int main() {
    char *buf = malloc(50);
    sprintf(buf, "Hello, world!");
    puts(buf);
    free(buf);
    return 0;
}
EOF
$ cc mem.c main.c
$ ./a.out
0x40077e: malloc(50) = 0x22f7010
Hello, world!

(We could use __attribute__((constructor)), but that trick isn't necessary: Glibc handily provides __malloc_initialize_hook as another way to load run code before main.)

ephemient
  • 198,619
  • 38
  • 280
  • 391
  • The malloc hooks in glbic were removed in glibc 2.24 and later, some years after this answer was posted. (The current version of glibc on my system is 2.31) – Linas Jan 15 '23 at 01:11
7

To fix both the macro-replacement problem, and make LINE etc work as you're hoping they will:

#define malloc(X) my_malloc((X), __FILE__, __LINE__, __FUNCTION__)

void* my_malloc(size_t size, const char *f, int l, const char *u)
{

    void *p = (malloc)(size);
    printf ("Allocated = %s, %d, %s, %x\n", f, l, u, p);
    return p;
}

(That way LINE and friends will be evaluated where the macro is expanded - otherwise they'd always be the same).

Enclosing the name (malloc) in parantheses prevents the macro malloc from being expanded, since it is a function-like macro.

caf
  • 233,326
  • 40
  • 323
  • 462
6

Unlike new/delete, there is no standard way to override malloc and free in standard C or C++.

However, most platforms will allow you to replace these standard library functions with your own, for example at link time.

If that doesn't work, and portability is necessary, first declare the replacement functions, then shadow the malloc/free functions with your replacement functions using macros, for example:

#include <stdlib.h>

void *myMalloc(size_t size) {
    return (malloc)(size);
}

void myFree(void *ptr) {
    (free)(ptr);
}

#define malloc(size) myMalloc(size)
#define free(ptr) myFree(ptr)
jarmod
  • 71,565
  • 16
  • 115
  • 122
LiraNuna
  • 64,916
  • 15
  • 117
  • 140
3

What if you implemented my_malloc() in a different file that doesn't see the #Define?

n8wrl
  • 19,439
  • 4
  • 63
  • 103
  • I think this is a more flexible solution. Most people look for #defines at the top of a file also, a point of confusion. – Dana the Sane Jul 07 '09 at 20:18
3

You should use LD_PRELOAD to overwrite this kind of function (Library Interposer is the actual name that I could not remember)..

Explanation here

Community
  • 1
  • 1
LB40
  • 12,041
  • 17
  • 72
  • 107
1

#define is a macro replacement. The call to malloc(size) is getting replaced by my_malloc(size).

Fred Larson
  • 60,987
  • 18
  • 112
  • 174
1

If you try to #define malloc (a reserved identifier) then the behaviour of your program is undefined so you should try to find another way to address your problem. If you really need to do this then this may work.

#include <stdlib.h>

#define malloc(x) my_malloc(x)

void *my_malloc(size_t x)
{
        return (malloc)(x);
}

Function like macros are only expanded if they are found as macro-name followed by (. The extra parentheses around malloc mean that it is not of this form so it is not replaced by the preprocessor. The resulting syntax is still a valid function call so the real malloc will still be called.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 1
    What makes you think malloc is a reserved word? It's not, and even if it were, the preprocessor wouldn't care! – Christoph Jul 07 '09 at 20:49
  • Reserver 'identifier', not reserved word. 7.1.3/1 'All identifiers with external linkage in any of the following subclauses...' – CB Bailey Jul 07 '09 at 21:16
  • thanks, but then again: what does the preprocessor care? `malloc` is reserved in the context of *external linkage*, and *not* macro definition – Christoph Jul 07 '09 at 21:43
  • The preprocessor is just part of the implementation. The implementation is allowed to rely on the programmer not doing things that result in undefined behaviour. Perhaps a standard library macro uses malloc in a way that relies on it not having been #define'd by the programmer. 7.1.3/2 cleary states that if a program defines a reserved identifier as a macro name then the behaviour is undefined. It might be something allowed by some implementations, but that's a non-portable language extension. – CB Bailey Jul 07 '09 at 22:05
  • @Charles: 7.1.3 §2 seems inconsistent with 7.1.4, especially footnote 163), which explicitly mentions the use of `#undef` to reveal the prototype of a library function which might be shadowed by the definition of a function-like macro; so if you use `#undef malloc` to make sure you're dealing with an actual prototype (or just don't include `` at all), it should be reasonably safe to use a `#define`; I'll have to meditate some more over the exact wording of the standard to see where this perceived contradiction comes from; only considering 7.1.3 §2, I'd have to agree with you – Christoph Jul 07 '09 at 23:35
  • It's probably a good rule of thumb that, if you have to meditate over the standard to determine whether something is allowed, it's probably a bad idea to do it anyway. – bdonlan Jul 08 '09 at 02:31
  • 7.1.3 does include a clause saying "except as permitted by 7.1.4". 7.1.4 gives the program license to do some things such as #undef a masking macro or forward declare a standard library function. It doesn't give the program license to declare a macro with the same name as a library function and 7.1.3 expressly forbids this. I don't see the inconsistency. You're footnote numbering is inconsistent with my copy of the standard (ISO/IEC 9899:1999), so we may be looking at different versions. – CB Bailey Jul 08 '09 at 04:54
-2
#define malloc(X) my_malloc((X)) 

void* my_malloc(size_t size) 
{ 
    #define my_malloc(X) malloc((X)) 

    void *p = malloc(size); 
    printf ("Allocated = %s, %s, %s, %x\n",__FILE__, __LINE__, __FUNCTION__, p); 
    return p; 
} 

Here inside the function my_malloc, #define my_malloc(X) malloc((X)) will work. Outside this function it has no effect.Therefor, C malloc function will be invoked inside my_malloc

sukumar
  • 131
  • 1
  • 7