Crear una función de envoltura para malloc y gratis en C

Oye, estoy intentando crear funciones de envoltura gratis y malloc en C para ayudarme a notificarme sobre las pérdidas de memoria. ¿Alguien sabe cómo declarar estas funciones así que cuando llamo a malloc () y libre () llamará a mis funciones personalizadas y no a las funciones lib estándar?

Tienes pocas opciones:

  1. Solución específica de GLIBC (principalmente Linux). Si su entorno de comstackción es glibc con gcc , la forma preferida es usar los ganchos malloc . No solo le permite especificar malloc personalizado y free , sino que también identificará al que llama por la dirección de retorno en la stack.

  2. Solución específica POSIX. Defina malloc y free como envoltorios para las rutinas de asignación originales en su ejecutable, lo que “anulará” la versión de libc. Dentro del contenedor puede llamar a la implementación original de malloc , que puede buscar usando dlsym con el manejador RTLD_NEXT . Su aplicación o biblioteca que define las funciones de contenedor debe vincularse con -ldl .

     #define _GNU_SOURCE #include  #include  void* malloc(size_t sz) { void *(*libc_malloc)(size_t) = dlsym(RTLD_NEXT, "malloc"); printf("malloc\n"); return libc_malloc(sz); } void free(void *p) { void (*libc_free)(void*) = dlsym(RTLD_NEXT, "free"); printf("free\n"); libc_free(p); } int main() { free(malloc(10)); return 0; } 
  3. Linux específico. Puede anular las funciones de bibliotecas dinámicas de forma no invasiva si las especifica en la variable de entorno LD_PRELOAD .

     LD_PRELOAD=mymalloc.so ./exe 
  4. Mac OSX específico.

    Igual que Linux, excepto que DYLD_INSERT_LIBRARIES la variable de entorno DYLD_INSERT_LIBRARIES .

Puede hacer la función de envoltura y “sobrescribir” con LD_PRELOAD, de forma similar al ejemplo que se muestra anteriormente.

 LD_PRELOAD=/path.../lib_fake_malloc.so ./app 

Pero recomiendo hacer esto “un poco” más inteligente, me refiero a llamar a dlsym una vez .

 #define _GNU_SOURCE #include  #include  #include  void* malloc(size_t size) { static void* (*real_malloc)(size_t) = NULL; if (!real_malloc) real_malloc = dlsym(RTLD_NEXT, "malloc"); void *p = real_malloc(size); fprintf(stderr, "malloc(%d) = %p\n", size, p); return p; } 

ejemplo que he encontrado aquí: http://www.jayconrod.com/cgi/view_post.py?23 publicación de Jay Conrod.

Pero lo que he encontrado realmente genial en esta página es que: el enlazador GNU proporciona una opción útil, – wrap . Cuando verifico “man ld” hay un ejemplo siguiente:

 void * __wrap_malloc (size_t c) { printf ("malloc called with %zu\n", c); return __real_malloc (c); } 

Estoy de acuerdo con ellos que es un “ejemplo trivial” :). Incluso dlsym no es necesario.

Permítanme citar una parte más de mi página “man ld”:

 --wrap=symbol Use a wrapper function for symbol. Any undefined reference to symbol will be resolved to "__wrap_symbol". Any undefined reference to "__real_symbol" will be resolved to symbol. 

Espero, la descripción está completa y muestra cómo usar esas cosas.

En C, el método que utilicé fue similar a:

 #define malloc(x) _my_malloc(x, __FILE__, __LINE__) #define free(x) _my_free(x) 

Esto me permitió detectar la línea y el archivo de donde se asignó la memoria sin demasiada dificultad. Debe ser multiplataforma, pero encontrará problemas si la macro ya está definida (lo cual solo debería ser el caso si está usando otro detector de fuga de memoria).

Si desea implementar lo mismo en C ++, el procedimiento es un poco más complejo pero usa el mismo truco.

Aquí hay un conjunto de funciones de envoltura que utilicé durante años (y aún lo hago cuando busco en C) para detectar memoria sin liberar, memoria libre varias veces, referencias a memoria libre, desbordamientos / desbordamientos de búfer, y liberar memoria que no fue asignado.

ftp://ftp.digitalmars.com/ctools.zip

Han existido por 25 años y han demostrado su valía.

Podría usar el preprocesador de macro para redefinir malloc y usar los paquetes de mem gratuitos, pero recomiendo que no lo haga, ya que no redirigirá las llamadas de biblioteca a malloc como lo hace strdup.

Si su objective es eliminar memory leaks, una forma más fácil y menos intrusiva es usar una herramienta como Valgrind (gratis) o Purify (costosa).

Si define sus propias funciones para malloc () y free () y lo vincula explícitamente con sus aplicaciones, sus funciones se deben usar con preferencia a las de la biblioteca.

Sin embargo, su función llamada ‘malloc’ no puede llamar a la función de biblioteca malloc, porque en ‘c’ no hay concepto de espacios de nombres separados. En otras palabras, tendrías que implementar las partes internas de Malloc y liberarte.

Otro enfoque sería escribir las funciones my_malloc () y my_free (), que llaman a las de la biblioteca estándar. Esto significa que cualquier código que llame a malloc tendría que ser cambiado para llamar a sus funciones my_xxx.

Perdón por reabrir una publicación de 7 años.

En mi caso, necesitaba envolver memalign / aligned_malloc en malloc. Después de probar otras soluciones, terminé implementando la que se detalla a continuación. Parece estar funcionando bien.

mymalloc.c .

 /* * Link-time interposition of malloc and free using the static * linker's (ld) "--wrap symbol" flag. * * Compile the executable using "-Wl,--wrap,malloc -Wl,--wrap,free". * This tells the linker to resolve references to malloc as * __wrap_malloc, free as __wrap_free, __real_malloc as malloc, and * __real_free as free. */ #include  void *__real_malloc(size_t size); void __real_free(void *ptr); /* * __wrap_malloc - malloc wrapper function */ void *__wrap_malloc(size_t size) { void *ptr = __real_malloc(size); printf("malloc(%d) = %p\n", size, ptr); return ptr; } /* * __wrap_free - free wrapper function */ void __wrap_free(void *ptr) { __real_free(ptr); printf("free(%p)\n", ptr); } 

Si está utilizando Linux, puede usar malloc_hook () (con GNU glibc). Esta función le permite a malloc llamar a su función antes de llamar al malloc real. La página man tiene un ejemplo sobre cómo usarla.

Si solo habla de la memoria que tiene bajo control, es decir, que está malloc y libre por sí mismo, puede echar un vistazo a rmdebug . Probablemente sea lo que va a escribir de todos modos, para que pueda ahorrar en algún momento. Tiene una licencia muy liberal, si eso debería ser importante para usted.

Yo personalmente lo uso en un proyecto, para buscar memory leaks, lo bueno es que es mucho más rápido que valgrind, sin embargo, no es tan potente por lo que no obtienes la stack de llamadas completa.