2008-11-04 1 views
31

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

+0

Сторона примечания, это то, что инструменты, такие как Valgrind. Если вы предпочитаете использовать что-то из коробки в Unix или Linux, Valgrind - хороший вариант. – sudo 2017-07-21 19:15:36

ответ

2

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

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

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

+0

И вы можете #define malloc my_malloc, чтобы ваш код работал без изменений. Но вам нужно быть последовательным в отношении использования - не используйте my_malloc, если память будет освобождена в библиотеке или наоборот. – 2008-11-04 17:04:29

+0

Пункты 2 и 3 вводят в заблуждение. – 2011-09-12 23:03:05

+0

@ Matt Joiner - можете ли вы подробно рассказать, пожалуйста? – Roddy 2011-09-16 07:46:25

62

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

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

  2. 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; 
    } 
    
  3. Linux специфичны. Вы можете переопределить функции из динамических библиотек неинвазивно, указав их в переменной окружения LD_PRELOAD.

    LD_PRELOAD=mymalloc.so ./exe 
    
  4. Mac OSX специфичны.

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

4

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

0

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

5

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

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

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

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

0

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

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

5

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

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

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

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

12

Вы можете сделать обертку и «перезаписать» функцию с помощью 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 шатуны.

Но что я нашел действительно здорово на этой странице, что: GNU линкер обеспечивает полезный вариант, --wrap. Когда я проверяю «человек ЛД» есть следующий пример:

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

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

Пусть, я приведу еще одну части моей страницы «человек Л.Д.»:

--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. 

Я надеюсь, описание полное и показывает, как использовать эти вещи.

2

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

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

mymalloc.c.

/* 
* Link-time interposition of malloc and free using the static 
* linker's (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); 
} 
Смежные вопросы