#c #c #libevent
#c #c #libevent
Вопрос:
У меня есть два файла:
// event_test_delete.cpp
#include <event.h>
int main() {
event_base* ev;
ev = event_init();
delete ev;
return 0;
}
И
// event_test_free.cpp
#include <event.h>
#include <cstdlib>
int main() {
event_base* ev;
ev = event_init();
free(ev);
return 0;
}
Когда я компилирую ( g event_test_delete.cpp -levent -o event_test_delete.o
) event_test_delete.cpp Я получаю ошибку:
event_test_delete.cpp : В функции ‘int main()’: event_test_delete.cpp:8:9: предупреждение: обнаружена возможная проблема при вызове оператора удаления: event_test_delete.cpp:5:14: предупреждение: ‘ev’ имеет неполный тип /usr/include/event.h:211:8: предупреждение: прямое объявление ‘struct event_base’ event_test_delete.cpp:8:9: примечание: ни деструктор, ни специфичный для класса оператор delete вызываться не будут, даже если они объявлены при определении класса.
Но когда я компилирую g event_test_free.cpp -levent -o event_test_free.o
event_test_free.cpp, я не получаю ту же ошибку, почему?
И второй вопрос (с использованием valgrind), почему происходит утечка памяти?
Вывод Valgrind для первого файла: (почему здесь Mismatched free() / delete / delete []
?)
azat:~/Desktop/event_test$ valgrind --показать достижимость =да --проверка утечки = полная ./event_test_delete.o ==4135 == Memcheck, детектор ошибок памяти ==4135== Авторские права (C) 2002-2010 и GNU GPL'd, Джулиан Сьюард и др. ==4135 == С использованием Valgrind-3.6.0.SVN-Debian и LibVEX; повторите с помощью -h для получения информации об авторских правах ==4135== Команда: ./event_test_delete.o ==4135== ==4135== Несоответствующий free() / delete / удалить [] ==4135== при 0x4023881: удаление оператора(void*) (vg_replace_malloc.c:387) ==4135== по 0x8048571: main (в /home/azat/Desktop/event_test/event_test_delete.o) ==4135 == Адрес 0x4323028 равен 0 байтам внутри выделенного блока размером 944 ==4135== в 0x402328F: calloc (vg_replace_malloc.c:467) ==4135== по 0x4047DA7: event_base_new (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x4047EF6: event_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x8048561: main (в /home/azat/Desktop/event_test/event_test_delete.o) ==4135== ==4135== ==4135 == СВОДКА КУЧИ: ==4135== используется при выходе: 672 байта в 5 блоках ==4135 == общее использование кучи: 6 распределений, 1 освобождение, выделено 1616 байт ==4135== ==4135 == 8 байт в блоках 1 косвенно теряются в записи о потерях 1 из 5 ==4135== в 0x4023F50: malloc (vg_replace_malloc.c:236) ==4135== по 0x4047C7D: event_base_priority_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x4047E8B: event_base_new (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x4047EF6: event_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x8048561: main (в /home/azat/Desktop/event_test/event_test_delete.o) ==4135== ==4135 == 12 (4 прямых, 8 косвенных) байт в блоках 1 определенно потеряны в записи потерь 2 из 5 ==4135== в 0x402328F: calloc (vg_replace_malloc.c:467) ==4135== по 0x4047C2D: event_base_priority_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x4047E8B: event_base_new (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x4047EF6: event_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x8048561: main (в /home/azat/Desktop/event_test/event_test_delete.o) ==4135== ==4135 == 256 байт в блоках 1 косвенно потеряны в записи о потерях 3 из 5 ==4135== в 0x402328F: calloc (vg_replace_malloc.c:467) ==4135== по 0x4056192: ??? (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x4047E46: event_base_new (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x4047EF6: event_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x8048561: main (в /home/azat/Desktop/event_test/event_test_delete.o) ==4135== ==4135 == 384 байта в блоках 1 косвенно потеряны в записи потерь 4 из 5 ==4135== в 0x4023F50: malloc (vg_replace_malloc.c:236) ==4135== по 0x405616C: ??? (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x4047E46: event_base_new (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x4047EF6: event_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x8048561: main (в /home/azat/Desktop/event_test/event_test_delete.o) ==4135== ==4135 == 660 (20 прямых, 640 косвенных) байт в блоках 1 определенно потеряны в записи потерь 5 из 5 ==4135== в 0x402328F: calloc (vg_replace_malloc.c:467) ==4135== по 0x4056157: ??? (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x4047E46: event_base_new (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x4047EF6: event_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4135== по 0x8048561: main (в /home/azat/Desktop/event_test/event_test_delete.o) ==4135== ==4135 == КРАТКОЕ ОПИСАНИЕ УТЕЧКИ: ==4135 == определенно потеряно: 24 байта в 2 блоках ==4135 == косвенно потеряно: 648 байт в 3 блоках ==4135 == возможно, потеряно: 0 байт в 0 блоках ==4135 == все еще достижимо: 0 байт в 0 блоках ==4135 == подавлено: 0 байт в 0 блоках ==4135== ==4135== Для подсчета обнаруженных и подавленных ошибок выполните повторный запуск с помощью: -v ==4135 == СВОДКА ОШИБОК: 3 ошибки из 3 контекстов (подавлено: 28 из 7)
И для второго файла
azat:~/Desktop/event_test$ valgrind --показать достижимость =да --проверка утечки = полная ./event_test_free.o ==4140== Memcheck, детектор ошибок памяти ==4140== Авторские права (C) 2002-2010 и GNU GPL'd, Джулиан Сьюард и др. ==4140 == С использованием Valgrind-3.6.0.SVN-Debian и LibVEX; повторите с помощью -h для получения информации об авторских правах ==4140== Команда: ./event_test_free.o ==4140== ==4140== ==4140== СВОДКА КУЧИ: ==4140== используется при выходе: 672 байта в 5 блоках ==4140 == общее использование кучи: 6 распределений, 1 освобождение, выделено 1616 байт ==4140== ==4140 == 8 байт в блоках 1 косвенно теряются в записи о потерях 1 из 5 ==4140== в 0x4023F50: malloc (vg_replace_malloc.c:236) ==4140== по 0x4047C7D: event_base_priority_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x4047E8B: event_base_new (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x4047EF6: event_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x8048531: main (в /home/azat/Desktop/event_test/event_test_free.o) ==4140== == 4140 == 12 (4 прямых, 8 косвенных) байт в блоках 1 определенно потеряны в записи потерь 2 из 5 ==4140== в 0x402328F: calloc (vg_replace_malloc.c:467) ==4140== по 0x4047C2D: event_base_priority_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x4047E8B: event_base_new (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x4047EF6: event_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x8048531: main (в /home/azat/Desktop/event_test/event_test_free.o) ==4140== ==4140 == 256 байт в блоках 1 косвенно потеряны в записи о потерях 3 из 5 ==4140== в 0x402328F: calloc (vg_replace_malloc.c:467) ==4140== по 0x4056192: ??? (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x4047E46: event_base_new (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x4047EF6: event_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x8048531: main (в /home/azat/Desktop/event_test/event_test_free.o) ==4140== ==4140 == 384 байта в блоках 1 косвенно потеряны в записи потерь 4 из 5 ==4140== в 0x4023F50: malloc (vg_replace_malloc.c:236) ==4140== по 0x405616C: ??? (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x4047E46: event_base_new (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x4047EF6: event_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x8048531: main (в /home/azat/Desktop/event_test/event_test_free.o) ==4140== ==4140 == 660 (20 прямых, 640 косвенных) байт в блоках 1 определенно потеряны в записи потерь 5 из 5 ==4140== в 0x402328F: calloc (vg_replace_malloc.c:467) ==4140== по 0x4056157: ??? (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x4047E46: event_base_new (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x4047EF6: event_init (в /usr/lib/libevent-1.4.so.2.1.3) ==4140== по 0x8048531: main (в /home/azat/Desktop/event_test/event_test_free.o) ==4140== ==4140== КРАТКОЕ ОПИСАНИЕ УТЕЧКИ: ==4140 == определенно потеряно: 24 байта в 2 блоках ==4140== косвенно потеряно: 648 байт в 3 блоках ==4140 == возможно, потеряно: 0 байт в 0 блоках ==4140 == все еще достижимо: 0 байт в 0 блоках ==4140 == подавлено: 0 байт в 0 блоках ==4140== ==4140== Для подсчета обнаруженных и подавленных ошибок выполните повторный запуск с помощью: -v ==4140 == СВОДКА ОШИБОК: 2 ошибки из 2 контекстов (подавлено: 28 из 7)
Комментарии:
1. Можете ли вы показать нам реализацию
event_init()
. Обратите внимание, что этоdelete
может быть вызвано только в памяти, выделеннойnew
. Похоже, что valgrind указывает вам на эту ошибку в первом файле. Возможно, компилятор делает то же самое.2.
event_init()
реализует вlibevent
Ответ №1:
При использовании delete
компилятору необходимо увидеть тип объекта, на который указано, чтобы определить, есть ли какие-либо деструкторы, которые ему нужно вызвать в этот момент.
С другой стороны, valgrind, кажется, говорит, что память выделяется с использованием malloc и calloc. В этом случае вам не следует использовать delete
вообще, но возможно free
.
Во втором случае, при использовании free
, valgrind по-прежнему жалуется на утечки памяти. Одна из возможностей здесь заключается в том, что объект event содержит указатели на другие выделения, которые также необходимо освободить.
В этом случае должна быть другая функция, event_free
или event_release
которую вы должны вызвать, чтобы вернуть объект event. У вас есть один из них?
Комментарии:
1.
event_init
являетсяlibevent
функцией, monkey.org /~provos/libevent/doxygen-1.4.102.
memcached
( memcached.org ) мы тоже используемlibevent
, но я пытаюсь профилировать его с помощьюvalgrind
, и утечек памяти нет. Но в примере, который дает мнеlibevent
официальную страницу, есть утечки памяти. Но вопрос в том, как я могу избежать этой утечки памяти в моем случае?3. @azat — Ссылка ведет на типичную страницу doxygen, она описывает каждую функцию независимо, но ничего не говорит о том, в каком порядке вы должны их вызывать. Но поскольку вы получаете сообщение
event_base*
отevent_init()
, можно предположить, чтоevent_base_free
было бы неплохо снова его освободить. Но это всего лишь предположение! Я не знаю наверняка.
Ответ №2:
Первый вопрос: delete необходимо знать тип удаляемого указателя, поскольку для этого может потребоваться вызвать деструктор.
Второй вопрос: смотрите комментарий под вопросом. Нам нужно знать, что делает event_init и как он выделяет память для информирования о существующих утечках памяти. Тем не менее, хороший совет: доверяйте Valgrind.
Комментарии:
1. смотрите комментарии к следующему ответчику
Ответ №3:
Libevent написан не на C , и, следовательно, он не использует деструкторы. Вы никогда не должны использовать delete
для кода, который не был выделен с помощью new
.
Если вы прочитали руководство по libevent в разделе «освобождение базы событий», там указано, что вы должны использовать:
void event_base_free(struct event_base *base);
Кроме того, event_new
функция для выделения базы событий устарела (поскольку она не потокобезопасна), вам следует вместо этого использовать:
struct event_base *event_base_new(void);