как я могу переопределить malloc(), calloc(), free () и т.д. Под OS X?

StackOverflow https://stackoverflow.com/questions/929893

Вопрос

Предполагая последнюю версию XCode и GCC, каков правильный способ переопределить функции выделения памяти (я также предполагаю, что operator new / delete).Отладочные распределители памяти работают слишком медленно для игры, мне просто нужны некоторые базовые статистические данные, которые я могу сделать сам с минимальным воздействием.

Я знаю, что это легко в Linux из-за хуков, и это было тривиально в codewarrior десять лет назад, когда я писал HeapManager.

К сожалению, у smartheap больше нет версии для Mac.

Нет правильного решения

Другие советы

Я бы использовал предварительную загрузку библиотеки для этой задачи, потому что это не требует модификации запущенной программы.Если вы знакомы с обычным способом Unix для этого, то практически все сводится к замене LD_PRELOAD на DYLD_INSERT_LIBRARIES .

Первый шаг - создать библиотеку с таким кодом, как этот, затем создать ее, используя обычные параметры связывания с общей библиотекой (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);
}

Обратите внимание, что если вы также отклоняете calloc() и его реализация требует malloc(), вам может понадобиться дополнительный код, чтобы проверить, как вас вызывают.Программы на C ++ должны быть довольно безопасными, потому что new вызовы оператора malloc() в любом случае, но имейте в виду, что ни один стандарт этого не требует.Я никогда не сталкивался с реализацией, которая не использовала бы malloc(), хотя.

Наконец, настройте среду запуска для вашей программы и запустите ее (может потребоваться корректировка в зависимости от того, как ваша оболочка обрабатывает переменные среды).:

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

Видишь страница руководства по dyld для получения дополнительной информации о переменных среды динамического компоновщика.

Этот метод довольно общий.Однако есть и ограничения:

  • Вы не сможете перенаправлять прямые системные вызовы
  • Если само приложение обманывает вас, используя dlsym() для загрузки mallocесли вы укажете адрес, вызов не будет переадресован.Если, однако, вы не обманете его, также отвлекая dlsym!

Тот Самый malloc_default_zone техника, упомянутая на http://lists.apple.com/archives/darwin-dev/2005/Apr/msg00050.html похоже, все еще работает, см., например, http://code.google.com/p/fileview/source/browse/trunk/fileview/fv_zone.cpp?spec=svn354&r=354 для примера используйте то, что кажется похожим на то, что вы задумали.

После долгих поисков (включая сюда) и проблем с 10.7 я решил написать сообщение в блоге на эту тему: Как установить malloc-хукеры в OSX Lion

В конце поста вы найдете несколько хороших ссылок с более подробной информацией по этой теме.

Базовое решение:

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
}

Это старый вопрос, но я наткнулся на него, пытаясь сделать это сам.Мне стало интересно узнать об этой теме для личного проекта, над которым я работал, главным образом для того, чтобы убедиться, что то, что, как я думал, было автоматически освобождено, было правильно освобождено.В итоге я написал реализацию на C ++, которая позволяла мне отслеживать объем выделенной кучи и сообщать об этом, если я того пожелаю.

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

Как следует из названия, это зависит от OSX.Однако я смог сделать это в средах Linux, используя malloc_usable_size

Пример

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

Здание

$ 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

Надеюсь, это поможет кому-нибудь еще в будущем!

Если основную статистику, которая вам нужна, можно собрать в простой оболочке, быстрый (и довольно грязный) трюк заключается в простом использовании некоторых #define замена макроса.

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

    /* do your stat work? */

    return ptr;
}

и

#define malloc(sz_) _mymalloc(sz_)

Примечание:если макрос определен до того, как определение _mymalloc в конечном итоге заменит вызов malloc внутри этой функции, оставляя вас с бесконечной рекурсией...поэтому убедитесь, что это не так.Возможно, вы захотите явно #undef это перед определением этой функции и просто (повторно) определите его позже, в зависимости от того, где вы в конечном итоге включите его, чтобы, надеюсь, избежать этой ситуации.

Я думаю, что если вы определите malloc() и free() в вашем собственном файле .c, включенном в проект, компоновщик разрешит эту версию.

Итак, как вы собираетесь реализовать malloc?

Ознакомьтесь с подходом Эмери Бергера - автора распределителя накопительной памяти - для замены распределителя в OSX по адресу https://github.com/emeryberger/Heap-Layers/blob/master/wrappers/macwrapper.cpp (и несколько других файлов, которые вы можете отследить самостоятельно, следуя инструкциям includes).

Это дополняет ответ Алекса, но я подумал, что этот пример больше подходит для замены системного распределителя.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top