мой код (main.c):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void* __real_malloc(size_t size);
void __real_free(void* ptr);
void* __wrap_malloc(size_t size)
{
void *ptr = __real_malloc(size);
printf("custom malloc size=%ld ptr=%p\n", size, ptr);
return ptr;
}
void __wrap_free(void* ptr)
{
printf("custom free ptr=%p\n", ptr);
__real_free(ptr);
}
// gcc -o mybin main.c -Wl,--wrap=malloc -Wl,--wrap=free
int main() {
const char *original = "Hello, World!";
char *copy;
copy = strdup(original);
printf("Original: %s\n", original);
printf("Copy: %s\n", copy);
void *ptr = malloc(100);
free(ptr);
free(copy);
return 0;
}
мой результат:
Original: Hello, World!
Copy: Hello, World!
custom malloc size=100 ptr=0x55a845ef06d0
custom free ptr=0x55a845ef06d0
custom free ptr=0x55a845ef02a0
На странице руководства написано, что strdup вызывает malloc. почему я не вижу в выводе двух вызовов «custom malloc»? когда я вызываю malloc, это пользовательский вариант. когда strdup вызывает его, он является стандартным. почему ?
env: простая виртуальная машина x86 под управлением Ubuntu
На странице руководства написано, что память получена с помощью malloc. Я освобождаю память после strdup, я запускал дезинфицирующее средство адресов gcc и ничего не сообщал.
@CatalinDemergian Со страницы руководства ld (см. --wrap=symbol
): "Any undefined reference to symbol will be resolved to "__wrap_symbol". Any undefined reference to "__real_symbol" will be resolved to symbol"
. Таким образом, компоновщик исправит только неопределенные ссылки на malloc
, чтобы указать на вашу реализацию __wrap_malloc
. Возможно (действительно вероятно), что из-за способа построения libc
все внутренние ссылки на malloc
и т. д. уже разрешены, поэтому ваш __wrap_malloc
никогда не будет учитываться в таких случаях.
ltrace может рассказать вам кое-что интересное.
Небольшая придирка: формат size_t printf – %zu.
Также никогда не вызывайте printf()
из пользовательской malloc()
или free()
реализации. printf()
и многие другие подобные функции могут и будут вызывать malloc()
сами, и вы получите бесконечную рекурсию. Попробуйте добавить к звонку "...size=%ld ptr=%p\n", size, ptr )
больше, чем просто printf()
, и посмотрите, что произойдет.
Компоновщик может переноситься только в компилируемые функции. Вы вызываете printf, который определен в libc, и который компоновщик не может изменить.
Обычно пользовательские malloc загружаются с помощью LD_PRELOAD.
Возможно,
strdup
на самом деле вызывает неmalloc
, а какую-то другую функцию распределения памяти? Или (что более вероятно) возможно, он находится в библиотеке, которая уже полностью скомпонована, поэтому ваш процесс компоновки ничего не может с этим поделать?