Эй, я пытаюсь создать функции-оболочки бесплатно и malloc в C, чтобы уведомить меня об утечке памяти. Кто-нибудь знает, как объявить эти функции, поэтому, когда я вызываю malloc() и free(), он будет вызывать мои пользовательские функции, а не функции lib lib?
Создайте функцию обертки для malloc и освободите ее на C
Ответ 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. После того, как я попробовал другие решения, я закончил реализацию перечисленного ниже. Кажется, он работает нормально.
/*
* 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, однако он не настолько мощный, поэтому вы не получаете полный стек вызовов.