Эй, я пытаюсь создать функции-оболочки бесплатно и 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, однако он не настолько мощный, поэтому вы не получаете полный стек вызовов.