2009-07-07 13 views
9

Estoy intentando anular malloc haciendo esto.Problema al anular malloc

#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; 
} 

Sin embargo, esto está llamando indefinidamente my_malloc de forma recursiva (a causa de la llamada malloc dentro my_malloc). Quería llamar a la función C malloc dentro de my_malloc y no a la implementación de macro. ¿Podrías decirme cómo hacer eso?

Gracias.

+0

Tal vez debería cambiar el título en algo más específico. El problema realmente no tiene nada que ver con malloc o overrider, sino con macros de preprocesador y acceder al nombre original. –

+4

Esto no funcionará de la manera que desee: '__FILE__',' __LINE__' y '__FUNCTION__' (la sintaxis C99 sería' __Func__') siempre se expandirá al mismo valor de acuerdo con su ubicación en el archivo que contiene 'my_malloc() '; tienes que ponerlos en tu definición de macro y pasarlos a 'my_malloc()' como argumentos! – Christoph

Respuesta

20

Problema resuelto:

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__) 
+1

+1 para hacer que mi solución aparezca cuando presioné Cargar respuestas nuevas. :) La explicación es que un #define solo tiene efecto para el código que aparece DESPUÉS de que se invoca. –

+0

+1 - Di el motivo, usted dio la solución. –

+0

El problema con esto (y por qué no puede resolverse), es que solo funciona si no está considerando bibliotecas existentes que ya están compiladas y llamando a malloc (que su propio código puede ser responsable de administrar). En ese caso, puede hacer algo como esto: http://stackoverflow.com/questions/6083337/overriding-malloc-using-the-ld-preload-mechanism – ideasman42

3

¿Qué ocurre si implementó my_malloc() en un archivo diferente que no muestra #Define?

+0

Creo que esta es una solución más flexible. La mayoría de las personas también busca #defines en la parte superior de un archivo, un punto de confusión. –

1

#define es un reemplazo de macro. La llamada a malloc (tamaño) está siendo reemplazada por my_malloc (tamaño).

3

A diferencia de los nuevos/borrar, no hay forma estándar para anular malloc y libre en C estándar o C++.

Sin embargo, la mayoría de las plataformas de alguna manera le permitirán compensar estas funciones de biblioteca estándar con la suya, por ejemplo, en tiempo de enlace.

Si eso no funciona, y la portabilidad es necesario, primero declarar las funciones, a continuación, declarar las define:

#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) 
3

Debe utilizar LD_PRELOAD sobrescribir este tipo de función (Biblioteca mediadora es el nombre real que no podía recordar) ..

Explicación here

0

Si intenta #definemalloc (un identificador reservado), entonces el comportamiento de su programa no está definido de manera que y Debería tratar de encontrar otra forma de abordar su problema. Si realmente necesita hacer esto, entonces esto puede funcionar.

#include <stdlib.h> 

#define malloc(x) my_malloc(x) 

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

función como macros solamente se expanden si se encuentran como macro-name seguido por (. El paréntesis adicional alrededor de malloc significa que no es de esta forma por lo que no es reemplazado por el preprocesador. La sintaxis resultante sigue siendo una llamada de función válida por lo que aún se llamará al malloc real.

+0

¿Qué le hace pensar que malloc es una palabra reservada? No lo es, e incluso si lo fuera, ¡al preprocesador no le importaría! – Christoph

+0

Reserver 'identifier', palabra no reservada. 7.1.3/1 'Todos los identificadores con enlace externo en cualquiera de las siguientes subcláusulas ...' –

+0

gracias, pero de nuevo: ¿qué le importa al preprocesador? 'malloc' está reservado en el contexto de * external linkage *, y * not * macro definition – Christoph

13

Con Glibc, existe malloc_hook(3) como el manera apropiada de forma global interponer su propia función malloc.

#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! 

(Podríamos utilizar __attribute__((constructor)), pero ese truco no es necesario: Glibc cómodamente ofrece __malloc_initialize_hook como otra manera de cargar el código antes de ejecutar main.)

4

Para solucionar el problema, tanto macro-reemplazo, y crea LÍNEA etc trabajo como usted está esperando que lo harán:

#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; 
} 

(De esa manera LÍNEA serán evaluados y amigos, donde la macro se expande; de ​​lo contrario, siempre serían lo mismo).

Encerrar el nombre (malloc) en parantheses impide que la macro malloc se expanda, ya que se trata de una macro similar a una función.

0
#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; 
} 

Aquí dentro del my_malloc función, #define my_malloc (X) malloc ((X)) va a funcionar. Fuera de esta función no tiene ningún efecto. Por lo tanto, se invocará la función C malloc dentro de my_malloc