Функция взаиморасположения работает только для malloc и не свободна

Я столкнулся с небольшой проблемой при мониторинге malloc и free через использование функции interposition.

При выполнении вставки функции для просто malloc, она работает как исключено. Тем не менее, когда вы пытаетесь вставить свободное, оно оказывается в цикле; мне кажется, что бесплатно вызывается рекурсивно, но я просто не знаю почему.

Это код для malloc и свободных функций. (Mod_malloc_free.c)

#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <dlfcn.h>

void* malloc(size_t size) {

   static void* (*real_malloc)(size_t) = NULL;

   printf("%s\n", "inside shared malloc");

   if(!real_malloc)
        real_malloc = dlsym(RTLD_NEXT, "malloc");

   void * p = real_malloc(size);

   printf("malloc(%d) = %p\n",size, p );

   printf("%s\n", "returning from shared malloc");

   return p;

   }

void free(void* ap ) {

    static void (*real_free)(void*) = NULL;

  printf("inside shared free...\n");

  if(!real_free)
       real_free = dlsym(RTLD_NEXT, "free");

   printf("free = %p\n", ap);

   real_free(ap);

}

Основное просто состоит из:

#include <stdio.h>
#include <malloc.h>

int main(void) {

    void * p = malloc(123);

    printf("p = %p\n",p );

    free(p);

    return 0;

}

Составлено как:

gcc -shared -ldl -fPIC mod_malloc_free.c -o libcustom.so

gcc -o smallMain -Wall smallMain.c

LD_PRELOAD =. / Libcustom.so ./smallMain

С наилучшими пожеланиями

Nyfiken

3 ответа

glibc обеспечивает реальный символ (не слабый) __ префикс. Так что попробуйте поискать символ __malloc а также __free,

И просто для предотвращения рекурсии, не используйте printf() или любые другие функции, которые могут потребоваться для выделения памяти внутри вашей обертки.

Скорее всего printf звонит free, Конечно, это подразумевает, что он также выполняет выделение памяти, поэтому возникает вопрос, почему вы не видите рекурсивные вызовы в malloc, Скорее всего printf называет альтернативу, такую ​​как calloc или же realloc,

Чтобы вставить только свой собственный код, используйте макросы для замены вызовов или свяжите свой код отдельно и используйте функции компоновщика для удаления malloc а также free перед связыванием с внешними библиотеками (такими как -unexported_symbol переключатель для версии Apple ld).

Вставить во весь код, удалить printf из вашей рутины. Вызовите более простые процедуры, такие как fputs вместо. В качестве альтернативы используйте статический флаг для подавления рекурсии:

void free(void *ap)
{
    static void (*RealFree)(void *) = 0;
    If (!RealFree)
        RealFree = dlsym(RTLD_NEXT, "free");

    static int InsideCall = 0;
    if (!InsideCall)
    {
        InsideCall = 1;
        … Do stuff…
        InsideCall = 0;
    }
}

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

Я бы посоветовал вам использовать макрос для замены malloc/free своими собственными функциями вместо использования указателей на функции.

Примерно так должно это сделать:

 #ifdef REPLACE_MALLOC
 #define malloc(x) my_mallc(x)
 #define free(x)   my_free(x)
 #endif

Не забудьте сделать:

 #undef malloc
 #undef free

до вашей фактической реализации.

Однако обратите внимание, что технически это не "правильно" - вы не должны использовать макросы для вещей, которые являются частью стандартной библиотеки, поэтому, пожалуйста, не стоните здесь, если она перестает работать - в частности, Microsoft уже делает что-то подобное заменить malloc с его отладочной версией в сборках отладки.

Другие вопросы по тегам