Crie uma function de wrapper para malloc e livre em C

Ei, eu estou tentando criar funções de wrapper gratuitamente e malloc em C para ajudar a notificar-me de vazamentos de memory. Alguém sabe como declarar essas funções assim quando eu chamo malloc () e free () ele vai chamar minhas funções personalizadas e não as funções de lib de padrões?

Você tem poucas opções:

  1. Solução específica de GLIBC (principalmente Linux). Se o seu ambiente de compilation é glibc com gcc , a maneira preferida é usar ganchos malloc . Não só permite especificar custom malloc e free , mas também identifica o chamador pelo endereço de retorno na pilha.

  2. Solução específica de POSIX. Defina malloc e malloc como wrappers para as rotinas de alocação originais em seu executável, o que “replaceá” a versão da libc. Dentro do wrapper você pode chamar a implementação malloc original, que pode ser consultada usando o dlsym com o identificador RTLD_NEXT . Seu aplicativo ou biblioteca que define as funções do wrapper precisa se vincular a -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. Você pode replace funções de bibliotecas dinâmicas de forma não invasiva, especificando-as na variável de ambiente LD_PRELOAD .

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

    O mesmo que o Linux, exceto que você usará a variável de ambiente DYLD_INSERT_LIBRARIES .

Você pode fazer o wrapper e a function “overwrite” com LD_PRELOAD – como no exemplo mostrado anteriormente.

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

Mas eu recomendo fazer isso “um pouco” mais esperto, quero dizer chamando dlsym uma 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; } 

exemplo que eu encontrei aqui: http://www.jayconrod.com/cgi/view_post.py?23 postar por Jay Conrod.

Mas o que achei muito legal nesta página é que: GNU linker fornece uma opção útil, –wrap . Quando eu marquei “man ld”, há o seguinte exemplo:

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

Eu concordo com eles que é “exemplo trivial” :). Mesmo dlsym não é necessário.

Deixe-me citar mais uma parte da minha 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 que a descrição esteja completa e mostre como usar essas coisas.

Em C, o método que usei foi semelhante a:

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

Isso me permitiu detectar a linha e o arquivo de onde a memory foi alocada sem muita dificuldade. Ele deve ser de plataforma cruzada, mas encontrará problemas se a macro já estiver definida (o que deve ser o caso apenas se você estiver usando outro detector de memory leaks).

Se você quiser implementar o mesmo em C ++, o procedimento é um pouco mais complexo, mas usa o mesmo truque.

Aqui está um conjunto de funções de invólucro que usei por anos (e ainda faço quando mergulho em C) para detectar memory não-liberada, memory livre várias vezes, referências a memory livre, buffer overflows / underflows e liberação de memory que não foi alocado.

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

Eles estão por aí há 25 anos e provaram a si mesmos.

Você poderia usar o pré-processador de macros para redefinir o malloc e liberar para usar os pacotes do mem, mas eu recomendo que ele não redirecione as chamadas da biblioteca para o malloc, como acontece com o strdup.

Se o seu objective é eliminar vazamentos de memory, uma maneira mais fácil e menos intrusiva é usar uma ferramenta como a Valgrind (gratuita) ou a Purify (dispendiosa).

Se você definir suas próprias funções para malloc () e free () e vincular explicitamente isso a seus aplicativos, suas funções devem ser usadas de preferência para aquelas na biblioteca.

No entanto, sua function chamada ‘malloc’ não pode chamar a function malloc da biblioteca, porque em ‘c’ não há conceito de namespaces separados. Em outras palavras, você teria que implementar as partes internas do malloc e se libertar.

Outra abordagem seria escrever as funções my_malloc () e my_free (), que chamam as bibliotecas padrão. Isso significaria que qualquer código chamado malloc teria que ser alterado para chamar suas funções my_xxx.

Desculpe por reabrir um post de 7 anos de idade.

No meu caso, eu precisava envolver memalign / align_malloc sob malloc. Depois de tentar outras soluções, acabei implementando a lista abaixo. Parece estar funcionando bem.

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

Se você estiver usando Linux, você pode usar malloc_hook () (com GNU glibc). Esta function permite ao malloc chamar sua function antes de chamar o malloc real. A man page tem um exemplo de como usá-lo.

Se você é apenas falar sobre a memory que você tem sob controle, ou seja, que você malloc e livre por conta própria, você pode dar uma olhada no rmdebug . Provavelmente é o que você vai escrever de qualquer maneira, então você pode economizar algum dia. Tem uma licença muito liberal, se isso for importante para você.

Eu pessoalmente uso isso em um projeto, para procurar por vazamentos de memory, o mais legal é que ele é muito mais rápido que o valgrind, no entanto, ele não é tão poderoso, então você não obtém a pilha completa de chamadas.