Pergunta

Assumindo que o mais recente XCode e GCC, o que é a maneira correta de substituir as funções de alocação de memória (eu acho operator new / delete também). Os alocadores de memória de depuração são muito lentos para um jogo, eu só preciso de algumas estatísticas básicas que posso fazer eu mesmo com um impacto mínimo.

Eu sei que é fácil no Linux devido aos ganchos, e este era trivial em CodeWarrior anos dez atrás, quando eu escrevi HeapManager.

Infelizmente SmartHeap já não tem uma versão para Mac.

Nenhuma solução correta

Outras dicas

Gostaria de usar pré-carregamento biblioteca para esta tarefa, porque ele não requer modificação do programa em execução. Se você estiver familiarizado com a maneira usual Unix para fazer isso, é quase uma questão de substituir LD_PRELOAD com DYLD_INSERT_LIBRARIES.

O primeiro passo é criar uma biblioteca com código como este, em seguida, construí-lo usando opções de biblioteca que liga compartilhados regulares (gcc -dynamiclib):

void *malloc(size_t size)
{
    void * (*real_malloc)(size_t);
    real_malloc = dlsym(RTLD_NEXT, "malloc");

    fprintf(stderr, "allocating %lu bytes\n", (unsigned long)size);
    /* Do your stuff here */

    return real_malloc(size);
}

Note que se você também calloc() desvio e sua chamadas de implementação malloc(), você pode precisar de código adicional para verificar como está sendo chamado. programas em C ++ deve ser bastante seguro, pois as chamadas operador new malloc() qualquer maneira, mas estar cientes de que há Enforces padrão que. Eu nunca encontrei uma implementação que não usou malloc(), no entanto.

Finalmente, configurar o ambiente em execução para o seu programa e lançá-lo (pode exigir ajustes dependendo de como o shell variáveis ??de ambiente alças):

export DYLD_INSERT_LIBRARIES=./yourlibrary.dylib
export DYLD_FORCE_FLAT_NAMESPACE=1
yourprogram --yourargs

manual do dyld página para mais informações sobre as variáveis ??de ambiente vinculador dinâmico.

Este método é bastante genérico. Há limitações, no entanto:

  • Você não será capaz de desviar as chamadas do sistema diretos
  • Se a aplicação em si truques você usando dlsym() para o endereço de carga do malloc, a chamada não será desviado. A menos que, no entanto, você enganá-lo de volta, também desviar dlsym!

A técnica malloc_default_zone mencionado em http: // listas. apple.com/archives/darwin-dev/2005/Apr/msg00050.html parece trabalho ainda, ver, por exemplo http: // código. google.com/p/fileview/source/browse/trunk/fileview/fv_zone.cpp?spec=svn354&r=354 para um exemplo de uso que parece ser semelhante ao que você pretende.

Depois de muito procurar (aqui incluído) e problemas com 10,7 eu decidi escrever um blog sobre este tema: Como ganchos malloc set em OSX Lion

Você vai encontrar algumas ligações boas no final do post com mais informações sobre este tema.

A solução básica:

malloc_zone_t *dz=malloc_default_zone();
if(dz->version>=8)
{
    vm_protect(mach_task_self(), (uintptr_t)malloc_zones, protect_size, 0, VM_PROT_READ | VM_PROT_WRITE);//remove the write protection
}
original_free=dz->free;
dz->free=&my_free; //this line is throwing a bad ptr exception without calling vm_protect first
if(dz->version==8)
{
    vm_protect(mach_task_self(), (uintptr_t)malloc_zones, protect_size, 0, VM_PROT_READ);//put the write protection back
}

Esta é uma questão de idade, mas me deparei com ele ao tentar fazer isso sozinho. Fiquei curioso sobre este tópico para um projeto pessoal que eu estava trabalhando, principalmente para se certificar de que o que eu pensei foi automaticamente desalocada estava sendo adequadamente desalocada. Acabei escrevendo uma implementação C ++ para permitir-me para controlar a quantidade de heap alocado e relatá-lo para fora se eu assim o escolheu.

https://gist.github.com/monitorjbl/3dc6d62cf5514892d5ab22a59ff34861

Como observa o nome, este é específico da OSX. No entanto, eu era capaz de fazer isso em ambientes Linux usando o malloc_usable_size

Exemplo

#define MALLOC_DEBUG_OUTPUT
#include "malloc_override_osx.hpp"

int main(){
   int* ip = (int*)malloc(sizeof(int));
   double* dp = (double*)malloc(sizeof(double));

   free(ip);
   free(dp);
}

Construção

$ clang++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk \
          -pipe -stdlib=libc++ -std=gnu++11 -g -o test test.cpp
$ ./test
0x7fa28a403230 -> malloc(16) -> 16
0x7fa28a403240 -> malloc(16) -> 32
0x7fa28a403230 -> free(16) -> 16
0x7fa28a403240 -> free(16) -> 0

Espero que isso ajude alguém no futuro!

Se as estatísticas básicas que você precisa pode ser coletados em um invólucro simples, um rápido (e um bocado sujo) truque é usar apenas alguns #define substituição macro.

void* _mymalloc(size_t size)
{
    void* ptr = malloc(size);

    /* do your stat work? */

    return ptr;
}

e

#define malloc(sz_) _mymalloc(sz_)

Nota : se a macro é definido antes a definição _mymalloc ele vai acabar substituindo a chamada malloc dentro daquela função deixando-o com recursividade infinita ... assim garantir isso não é o caso. Você pode querer #undef explicitamente antes que definição de função e simplesmente (re) definir-lo depois, dependendo de onde você acaba incluindo-lo para evitar esperançosamente esta situação.

Eu acho que se você definir um malloc () e free () em seu próprio arquivo .c incluído no projeto o vinculador irá resolver essa versão.

Agora, então, como é que você pretende implementar malloc?

Confira Emery Berger - o autor do alocador de memória Hoard - abordagem para substituir o alocador no OSX em https://github.com/emeryberger/Heap-Layers/blob/master/wrappers/macwrapper.cpp (e alguns outros arquivos que você pode traçar-se, seguindo o inclui).

Esta é complementar a resposta de Alex, mas eu pensei que este exemplo foi mais direto ao ponto de substituir o sistema previsto alocador.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top