Pregunta

Si se asume la última XCode y GCC, ¿cuál es la forma correcta de anular las funciones de asignación de memoria (supongo operador new / delete también). Los asignadores de memoria de depuración son demasiado lentos para un juego, sólo necesito algunas estadísticas básicas que puedo hacer yo mismo con un impacto mínimo.

Sé que es fácil en Linux debido a los ganchos, y esto fue una tarea trivial bajo CodeWarrior hace diez años cuando escribí HeapManager.

Lamentablemente SmartHeap ya no tiene una versión para Mac.

No hay solución correcta

Otros consejos

Me gustaría utilizar precarga biblioteca para esta tarea, ya que no requiere la modificación del programa en ejecución. Si está familiarizado con la forma habitual de Unix para hacer esto, es casi una cuestión de reemplazar LD_PRELOAD con DYLD_INSERT_LIBRARIES.

El primer paso es crear una biblioteca con código como este, entonces construirlo usando la biblioteca que une las opciones regulares compartidos (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);
}

Tenga en cuenta que si también desviar calloc() y su aplicación malloc() llamadas, es posible que necesite un código adicional para comprobar cómo está siendo llamado. Los programas en C ++ debe ser bastante segura ya que el operador new llama malloc() todos modos, pero tenga en cuenta que hay una norma que hace cumplir. Nunca me he encontrado una aplicación que no utilizó malloc(), sin embargo.

Finalmente, configurar el entorno de ejecución de su programa y ejecutarlo (puede requerir ajustes en función de cómo maneja su shell variables de entorno):

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

la dyld página del manual de más información acerca de las variables de entorno enlazador dinámico.

Este método es bastante genérico. Hay limitaciones, sin embargo:

      
  • Usted no será capaz de desviar las llamadas al sistema directos   
  • Si la propia aplicación le engaña mediante el uso de dlsym() para cargar la dirección del malloc, no se desviarán la llamada. A menos que, sin embargo, usted truco en sentido contrario también desviar dlsym!

La técnica malloc_default_zone mencionado en http: // listas. apple.com/archives/darwin-dev/2005/Apr/msg00050.html parece seguir funcionando, ver por ejemplo, http: // código. google.com/p/fileview/source/browse/trunk/fileview/fv_zone.cpp?spec=svn354&r=354 para un uso de ejemplo que parece ser similar a lo que se propone.

Después de mucha búsqueda (aquí se incluye) y los problemas con el 10,7 decidí escribir un post sobre este tema: Cómo establecer ganchos malloc en OSX Lion

Usted encontrará algunos buenos enlaces al final del post con más información sobre este tema.

La solución 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 es una vieja pregunta, pero me encontré con que al intentar hacerlo yo mismo. Tengo curiosidad acerca de este tema para un proyecto personal que estaba trabajando, sobre todo para asegurarse de que lo que pensé que desasignado automáticamente se cancela la asignación siendo adecuadamente. Terminé de escribir una aplicación C ++ que me permita realizar un seguimiento de la cantidad de montón asignado e informar de ello a cabo si así lo elegimos.

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

Como señala el nombre, se trata de OSX-específica. Sin embargo, yo era capaz de hacer esto en entornos Linux utilizando el malloc_usable_size

Ejemplo

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

Edificio

$ 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 esto ayude a alguien más en el futuro!

Si las estadísticas básicas que necesita puede ser recogido en un simple envoltorio, un truco rápido (y algo sucia) es sólo con algunos #define macro reemplazo.

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

    /* do your stat work? */

    return ptr;
}

y

#define malloc(sz_) _mymalloc(sz_)

Nota: : si se define la macro antes la definición _mymalloc que va a terminar reemplazando la llamada malloc dentro de esa función dejándole con la recursividad infinita ... así asegurar esto no es el caso. Es posible que desee #undef explícitamente antes de esa definición de la función y simplemente (re) definir él después dependiendo de dónde terminan incluyendo a evitar esta situación es de esperar.

Creo que si se define un malloc () y free () en su propio archivo .c incluidos en el proyecto el enlazador resolverá esa versión.

Ahora bien, ¿cómo se va a implementar malloc?

Salida Emery Berger - el autor de la memoria del asignador Tesoro - enfoque para reemplazar el asignador en OSX https://github.com/emeryberger/Heap-Layers/blob/master/wrappers/macwrapper.cpp (y algunos otros archivos que puede rastrear mismo siguiendo la incluye).

Este es complementaria a la respuesta de Alex, pero pensé que este ejemplo era más para-el-punto de sustituir el sistema proporcionado asignador.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top