Проблема в переопределении malloc

Я пытаюсь переопределить 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, а не реализацию макроса. Не могли бы вы дать мне знать, как это сделать?

Благодарю.

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

Ответы на вопрос(9)

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

#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

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

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

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

#include <stdlib.h>

#define malloc(x) my_malloc(x)

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

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

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

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

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

В отличие от 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)

С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.)

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

Решение Вопроса

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

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__)
 07 июн. 2014 г., 02:55
Проблема с этим (и почему это можетnot решено), работает ли оно только в том случае, если вы не рассматриваете существующие библиотеки, которые уже скомпилированы, и вызываете malloc (которым может управлять ваш собственный код). В этом случае вы можете сделать что-то вроде этого:stackoverflow.com/questions/6083337/…
 07 июл. 2009 г., 22:07
+1 - я дал причину, ты дал решение.
 07 июл. 2009 г., 22:07
+1 за то, что мое решение появилось, когда я нажал «Загрузить новые ответы». :) Объяснение состоит в том, что #define вступает в силу только для кода, который появляется ПОСЛЕ того, как он вызван.

Ваш ответ на вопрос