Подтвердить что ты не робот

Создайте функцию обертки для malloc и освободите ее на C

Эй, я пытаюсь создать функции-оболочки бесплатно и malloc в C, чтобы уведомить меня об утечке памяти. Кто-нибудь знает, как объявить эти функции, поэтому, когда я вызываю malloc() и free(), он будет вызывать мои пользовательские функции, а не функции lib lib?

4b9b3361

Ответ 1

У вас есть несколько вариантов:

  • GLIBC-специфическое решение (в основном Linux). Если ваша среда компиляции glibc с gcc, предпочтительным способом является использование malloc hooks. Он не только позволяет указать пользовательские malloc и free, но также будет идентифицировать вызывающего абонента по обратному адресу в стеке.

  • Решение, ориентированное на POSIX. Определите malloc и free как обертки для исходных процедур выделения в вашем исполняемом файле, которые будут "переопределять" версию из libc. Внутри обертки вы можете вызвать оригинальную реализацию malloc, которую вы можете найти с помощью dlsym с дескриптором RTLD_NEXT. Вашему приложению или библиотеке, которая определяет функции-обертки, необходимо связать с -ldl.

    #define _GNU_SOURCE
    #include <dlfcn.h>
    #include <stdio.h>
    
    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;
    }
    
  • Специфические для Linux. Вы можете переопределить функции из динамических библиотек неинвазивно, указав их в переменной среды LD_PRELOAD.

    LD_PRELOAD=mymalloc.so ./exe
    
  • Спецификация Mac OSX.

    То же, что и Linux, за исключением того, что вы будете использовать переменную среды DYLD_INSERT_LIBRARIES.

Ответ 2

Вы можете использовать функцию обертки и "перезаписать" с помощью LD_PRELOAD - аналогично примеру, показанному ранее.

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

Но я рекомендую сделать это "немного" умнее, я имею в виду вызов dlsym один раз.

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

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

Например, я нашел здесь: http://www.jayconrod.com/cgi/view_post.py?23 сообщение от Jay Conrod.

Но то, что мне показалось действительно классным на этой странице, заключается в следующем: GNU linker предоставляет полезную опцию - wrap. Когда я проверяю "man ld", есть следующий пример:

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

Я согласен с ними, что "тривиальный пример":). Даже dlsym не нужен.

Позвольте, я приведу еще одну часть моей страницы "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.

Надеюсь, описание будет полным и покажет, как использовать эти вещи.

Ответ 3

В C метод, который я использовал, был похож на:

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

Это позволило мне определить строку и файл, где память была выделена без особых трудностей. Он должен быть кросс-платформенным, но столкнется с проблемами, если макрос уже определен (что должно быть только в том случае, если вы используете другой детектор утечки памяти.)

Если вы хотите реализовать то же самое в С++, процедура будет более сложной , но использует тот же трюк.

Ответ 4

Вот набор функций обертки, которые я использовал в течение многих лет (и все еще делаю, когда я погружаюсь в C), чтобы обнаруживать несвободную память, свободную память в несколько раз, ссылки на свободную память, переполнение/переполнение буфера и освобождая память, которая не была выделена.

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

Они были в течение 25 лет и зарекомендовали себя.

Вы можете использовать препроцессор макросов, чтобы переопределить malloc и бесплатно использовать mem-пакеты, но я рекомендую против него, потому что он не будет перенаправлять вызовы библиотеки в malloc, как то, что делает strdup.

Ответ 5

Если ваша цель - устранить утечки памяти, проще, менее навязчивым способом является использование такого инструмента, как Valgrind (бесплатно) или Purify (дорого).

Ответ 6

Если вы определяете свои собственные функции для malloc() и free() и явно связываете их с вашими приложениями, ваши функции должны использоваться в предпочтении тем, которые находятся в библиотеке.

Однако ваша функция под названием "malloc" не может вызывать функцию malloc библиотеки, потому что в "c" нет понятия отдельных пространств имен. Другими словами, вам нужно будет внедрить внутренности malloc и освободить себя.

Другим подходом было бы написать функции my_malloc() и my_free(), которые вызывают стандартные библиотечные. Это означало бы, что любой код, вызывающий malloc, должен быть изменен для вызова ваших функций my_xxx.

Ответ 7

Извините за повторное открытие 7-летнего поста.

В моем случае мне нужно было поместить memalign/aligned_malloc в malloc. После того, как я попробовал другие решения, я закончил реализацию перечисленного ниже. Кажется, он работает нормально.

mymalloc.c.

/* 
 * Link-time interposition of malloc and free using the static
 * linker (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 <stdio.h>

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

Ответ 8

Если вы используете Linux, вы можете использовать malloc_hook() (с GNU glibc). Эта функция позволяет вам вызывать функцию malloc перед вызовом фактического malloc. На странице руководства есть пример того, как его использовать.

Ответ 9

Если вы говорите только о памяти, которую вы контролируете, т.е. о том, что вы malloc и свободны сами по себе, вы можете взглянуть на rmdebug. Наверное, это то, что вы собираетесь писать, так что вы можете когда-нибудь сэкономить. У этого есть очень либеральная лицензия, если это должно быть важно для вас.

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