Могу ли я перезаписать malloc, вызываемый библиотечными функциями?

мой код (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

Возможно, strdup на самом деле вызывает не malloc, а какую-то другую функцию распределения памяти? Или (что более вероятно) возможно, он находится в библиотеке, которая уже полностью скомпонована, поэтому ваш процесс компоновки ничего не может с этим поделать?

Some programmer dude 10.07.2024 12:07

На странице руководства написано, что память получена с помощью malloc. Я освобождаю память после strdup, я запускал дезинфицирующее средство адресов gcc и ничего не сообщал.

Catalin Demergian 10.07.2024 13:40

@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 никогда не будет учитываться в таких случаях.

G.M. 10.07.2024 14:00

ltrace может рассказать вам кое-что интересное.

Allan Wind 10.07.2024 16:11

Небольшая придирка: формат size_t printf – %zu.

uis 11.07.2024 18:22

Также никогда не вызывайте printf() из пользовательской malloc() или free() реализации. printf() и многие другие подобные функции могут и будут вызывать malloc() сами, и вы получите бесконечную рекурсию. Попробуйте добавить к звонку "...size=%ld ptr=%p\n", size, ptr ) больше, чем просто printf(), и посмотрите, что произойдет.

Andrew Henle 11.07.2024 20:29
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
6
113
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Компоновщик может переноситься только в компилируемые функции. Вы вызываете printf, который определен в libc, и который компоновщик не может изменить.

Обычно пользовательские malloc загружаются с помощью LD_PRELOAD.

Другие вопросы по теме