tags:

views:

653

answers:

8

Hi,

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.

+2  A: 

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

n8wrl
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
+1  A: 

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

Fred Larson
+15  A: 

Problem solved:

void* my_malloc(size_t size)
{

    void *p = malloc(size);
    printf ("Allocated = %s, %s, %s, %x\n",__FILE__, __LINE__, __FUNCTION__, p);
    return p;
}
#define malloc(X) my_malloc((X))
Dave Gamble
+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
+1 - I gave the reason, you gave the solution.
Fred Larson
Thanks. It worked
+2  A: 

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

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

If that doesn't work, and portability is necessary, first declare the functions, then declare the defines:

#include <stdlib.h>

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

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

#define malloc(size) myMalloc(size)
#define free(ptr) myFree(ptr)
LiraNuna
+1  A: 

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

Explanation here

LB
+1  A: 

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.

Charles Bailey
What makes you think malloc is a reserved word? It's not, and even if it were, the preprocessor wouldn't care!
Christoph
Reserver 'identifier', not reserved word. 7.1.3/1 'All identifiers with external linkage in any of the following subclauses...'
Charles Bailey
thanks, but then again: what does the preprocessor care? `malloc` is reserved in the context of *external linkage*, and *not* macro definition
Christoph
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.
Charles Bailey
@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 `<stdlib.h>` 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
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
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.
Charles Bailey
+5  A: 

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
+2  A: 

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).

caf