От Эффективность по сравнению с намерением Andrew Koenig:
Первый, совсем не очевидно, что
++i
более эффективно, чемi++
, по крайней мере, где целочисленные переменные затронуты.
И:
, Таким образом, вопрос, который нужно задавать, не, какая из этих двух операций быстрее, это - какая из этих двух операций выражает более точно, что Вы пытаетесь выполнить. Я утверждаю, что, если Вы не используете значение выражения, никогда нет причины использовать
i++
вместо++i
, потому что никогда нет причины скопировать значение переменной, увеличьте переменную, и затем выбросьте копию.
Так, если бы получающееся значение не используется, я использовал бы ++i
. Но не потому что это более эффективно: потому что это правильно указывает мое намерение.
Проблема решена:
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__)
С Glibc существует malloc_hook (3)
как правильный способ глобально вставить свой собственный 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
расширяется, поскольку это макрос, подобный функции.
В отличие от 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)
Что, если бы вы реализовали my_malloc () в другом файле, который не видит #Define?
#define - это замена макроса. Вызов malloc (size) заменяется my_malloc (size).
Если вы попытаетесь использовать #define
malloc
(зарезервированный идентификатор), то поведение вашей программы не определено, поэтому вам следует попытаться найти другой способ решения вашей проблемы. проблема. Если вам действительно нужно это сделать, то это может сработать.
#include <stdlib.h>
#define malloc(x) my_malloc(x)
void *my_malloc(size_t x)
{
return (malloc)(x);
}
Такие функции, как макросы, раскрываются только в том случае, если они найдены как имя макроса
, за которым следует (
. Дополнительные скобки вокруг malloc
означает, что он не такой формы, поэтому препроцессор не заменяет его. Результирующий синтаксис по-прежнему является допустимым вызовом функции, поэтому реальный malloc все равно будет вызываться.
Вы должны использовать LD_PRELOAD, чтобы перезаписать этот вид функции (Library Interposer - это настоящее имя, которое я не мог вспомнить) ..
Пояснение здесь