Вопрос по c++, c – Проблема в переопределении malloc

10

Я пытаюсь переопределить malloc, делая это.

#define malloc(X) my_malloc((X))

void* my_malloc(size_t size)
{

    void *p = malloc(size);
    printf ("Allocated = %s, %s, %s, %x\n",__FILE__, __LINE__, __FUNCTION__, p);
    return p;
}

Однако это бесконечно рекурсивный вызов my_malloc (из-за вызова malloc внутри my_malloc). Я хотел вызвать функцию malloc C внутри my_malloc, а не реализацию макроса. Не могли бы вы дать мне знать, как это сделать?

Благодарю.

Это не сработает так, как вы хотите:__FILE__, __LINE__ а также__FUNCTION__ (Синтаксис C99 будет__func__) всегда будет расширяться до одного и того же значения в зависимости от их размещения в файле, содержащемmy_malloc(); Вы должны поместить их в определение макроса и передать ихmy_malloc() в качестве аргументов! Christoph
Возможно, следует изменить название на что-то более конкретное. Проблема на самом деле не имеет ничего общего с malloc или переопределением, а скорее с макросами препроцессора и доступом к исходному имени. David Rodríguez - dribeas

Ваш Ответ

9   ответов
1

#define - это замена макроса. Вызов malloc (size) заменяется на my_malloc (size).

-1
#define malloc(X) my_malloc((X)) 

void* my_malloc(size_t size) 
{ 
    #define my_malloc(X) malloc((X)) 

    void *p = malloc(size); 
    printf ("Allocated = %s, %s, %s, %x\n",__FILE__, __LINE__, __FUNCTION__, p); 
    return p; 
} 

Здесь внутри функции my_malloc, #define my_malloc (X) будет работать malloc ((X)). Вне этой функции это не имеет никакого эффекта. Поэтому функция C malloc будет вызываться внутри my_malloc

3

Вы должны использовать LD_PRELOAD для перезаписи такого рода функции (Library Interposer - это реальное имя, которое я не мог вспомнить) ..

объяснениеВот

0

Если вы попытаетесь#define malloc (зарезервированный идентификатор), тогда поведение вашей программы не определено, поэтому вы должны попытаться найти другой способ решения вашей проблемы. Если вам действительно нужно это сделать, то это может сработать.

#include <stdlib.h>

#define malloc(x) my_malloc(x)

void *my_malloc(size_t x)
{
        return (malloc)(x);
}

Такие функции, как макросы, раскрываются только в том случае, если они найдены какmacro-name с последующим(, Дополнительные скобки вокругmalloc означает, что он не имеет такой формы, поэтому он не заменен препроцессором. Полученный синтаксис все еще является допустимым вызовом функции, поэтому реальный malloc будет по-прежнему вызываться.

Reserver 'идентификатор', не зарезервированное слово. 7.1.3 / 1 "Все идентификаторы с внешней связью в любом из следующих подпунктов ..."
Что заставляет вас думать, что malloc - зарезервированное слово? Это не так, и даже если бы это было так, препроцессор не заботился бы!
спасибо, но опять же: что заботит препроцессор?malloc зарезервировано в контекстеexternal linkage, а такжеnot макроопределение
@Charles: 7.1.3 & # xA7; 2 кажется несовместимым с 7.1.4, особенно сноска 163), в которой явно упоминается использование#undef раскрыть прототип библиотечной функции, которая может быть затенена определением функционально-подобного макроса; так что если вы используете#undef malloc чтобы убедиться, что вы имеете дело с реальным прототипом (или просто не включать<stdlib.h> вообще), должно быть достаточно безопасно использовать#define; Мне придется еще немного поразмышлять над точной формулировкой стандарта, чтобы увидеть, откуда возникает это воспринимаемое противоречие; только учитывая 7.1.3 & # xA7; 2, я должен согласиться с вами
Препроцессор является лишь частью реализации. Реализация может полагаться на то, что программист не будет делать то, что приведет к неопределенному поведению. Возможно, макрос стандартной библиотеки использует malloc таким образом, чтобы он не был # определен программистом. 7.1.3 / 2 cleary утверждает, что если программа определяет зарезервированный идентификатор как имя макроса, то поведение не определено. Это может быть разрешено некоторыми реализациями, но это непереносимое расширение языка.
3

Что, если вы реализовали my_malloc () в другом файле, который не видит #Define?

Я думаю, что это более гибкое решение. Большинство людей также ищут #defines в верхней части файла, что вызывает путаницу.
3

В отличие от new / delete, нет стандартного способа переопределить malloc и free в стандарте C или C ++.

Тем не менее, большинство платформ так или иначе позволят вам изменить эти стандарты библиотека функционирует самостоятельно, например, во время ссылки.

Если это не работает, а переносимость необходима, сначала объявите функции, затем объявите определения:

#include <stdlib.h>

void *myMalloc(size_t size) {
// log
return malloc(size);
}

void myFree(void *ptr) {
// log
free(ptr);
}

#define malloc(size) myMalloc(size)
#define free(ptr) myFree(ptr)
13

СGlibc, Существуетmalloc_hook(3) какproper способ глобально вставить свой собственныйmalloc функция.

#include <stdio.h>
#include <malloc.h>

static void *(*old_malloc_hook)(size_t, const void *);

static void *new_malloc_hook(size_t size, const void *caller) {
    void *mem;

    __malloc_hook = old_malloc_hook;
    mem = malloc(size);
    fprintf(stderr, "%p: malloc(%zu) = %p\n", caller, size, mem);
    __malloc_hook = new_malloc_hook;

    return mem;
}

static void init_my_hooks(void) {
    old_malloc_hook = __malloc_hook;
    __malloc_hook = new_malloc_hook;
}

void (*__malloc_initialize_hook)(void) = init_my_hooks;
$ cat >mem.c <<'EOF'
(the code above)
EOF
$ cat >main.c <<'EOF'
#include <stdio.h>
#include <stdlib.h>
int main() {
    char *buf = malloc(50);
    sprintf(buf, "Hello, world!");
    puts(buf);
    free(buf);
    return 0;
}
EOF
$ cc mem.c main.c
$ ./a.out
0x40077e: malloc(50) = 0x22f7010
Hello, world!

(Мы могли бы использовать__attribute__((constructor)), но этот трюк не нужен: Glibc легко предоставляет__malloc_initialize_hook как еще один способ загрузить код запуска доmain.)

5

Чтобы исправить и проблему с заменой макросов, и сделатьLINE и т. д. работают так, как вы надеетесь:

#define malloc(X) my_malloc((X), __FILE__, __LINE__, __FUNCTION__)

void* my_malloc(size_t size, const char *f, int l, const char *u)
{

    void *p = (malloc)(size);
    printf ("Allocated = %s, %d, %s, %x\n", f, l, u, p);
    return p;
}

(СюдаLINE и друзья будут оцениваться там, где развернут макрос, в противном случае они всегда будут одинаковыми).

Вложение имени(malloc) в парантезах мешает макросmalloc от расширения, так как это функциональный макрос.

20

Задача решена:

void* my_malloc(size_t size, const char *file, int line, const char *func)
{

    void *p = malloc(size);
    printf ("Allocated = %s, %i, %s, %p[%li]\n", file, line, func, p, size);
    return p;
}
#define malloc(X) my_malloc( X, __FILE__, __LINE__, __FUNCTION__)
Проблема с этим (и почему это можетnot решено), работает ли оно только в том случае, если вы не рассматриваете существующие библиотеки, которые уже скомпилированы, и вызываете malloc (которым может управлять ваш собственный код). В этом случае вы можете сделать что-то вроде этого:stackoverflow.com/questions/6083337/…
+1 - я дал причину, ты дал решение.
+1 за то, что мое решение появилось, когда я нажал «Загрузить новые ответы». :) Объяснение состоит в том, что #define вступает в силу только для кода, который появляется ПОСЛЕ того, как он вызван.

Похожие вопросы