Недавно я написал приложение, которое получает доступ к базе данных Postgres через libpqxx, и оно сильно теряет память. Даже эта простая тестовая программа, основанная на примере http://pqxx.org/devprojects/libpqxx/doc/4.0/html/Reference/a00001.html Утечки, как нет завтра.
(Изменить: я добавил вызовы commit () и clear () в ответ на предложения. Та же утечка.)
#include <iostream>
#include <pqxx/pqxx>
#include <string>
#include <stdio.h>
int main()
{
try
{
pqxx::connection c("user=postgres");
int i = 0;
while(true)
{
pqxx::work w(c);
pqxx::result r = w.exec("SELECT 1");
w.commit();
i++;
if ( i % 1000 == 0 )
printf( "Cycle %d\n", i );
r.clear();
} //while
} //try
catch (const std::exception &e)
{
std::cerr << e.what() << std::endl;
return 1;
} //catch
} //main
После примерно 75 000 циклов цикла top показывает 206 МБ использования виртуальной памяти и продолжает расти. Я запустил аналогичную тестовую программу с 5000 циклами через valgrind и получил это:
==1647== 13,732,155 (219,868 direct, 13,512,287 indirect) bytes in 4,997 blocks are definitely lost in loss record 12 of 12
==1647== at 0x40060D5: operator new(unsigned int) (vg_replace_malloc.c:214)
==1647== by 0x404C0A9: pqxx::result::result(pg_result*, int, std::string const&, int) (in /usr/lib/libpqxx-4.0.so)
==1647== by 0x40309EF: pqxx::connection_base::make_result(pg_result*, std::string const&) (in /usr/lib/libpqxx-4.0.so)
==1647== by 0x4036D65: ??? (in /usr/lib/libpqxx-4.0.so)
==1647== by 0x405EFD6: pqxx::transaction_base::DirectExec(char const*, int) (in /usr/lib/libpqxx-4.0.so)
==1647== by 0x40416EA: pqxx::dbtransaction::do_exec(char const*) (in /usr/lib/libpqxx-4.0.so)
==1647== by 0x40618FA: pqxx::transaction_base::exec(std::string const&, std::string const&) (in /usr/lib/libpqxx-4.0.so)
==1647== by 0x80498F8: main (dbtest.cpp:21)
Есть идеи, что происходит? Очень трудно согласиться с тем, что широко используемая библиотека, такая как libpqxx, будет иметь такую серьезную ошибку, так что я могу сделать здесь неправильно?
Детали конфигурации:
(Окончательное редактирование: мне было проще заменить libpqxx на libpq, чем продолжать расследовать эту утечку памяти.)
Я не мог воспроизвести вашу проблему.
Ни с libpqxx-2.6.9, ни с libpqxx-4.0.1 (в настоящее время текущая стабильная версия).
Использование памяти постоянно.
$ valgrind —tool = memcheck run.sh
[…] Цикл 35000
Цикл 36000
^ C == 18420 ==
== 18420 == РЕЗЮМЕ КАРТЫ:
== 18420 == используется на выходе: 0 байтов в 0 блоках
== 18420 == общее использование кучи: 0 выделений, 0 освобождений, 0 выделенных байтов
== 18420 ==
== 18420 == Все блоки кучи были освобождены — утечки невозможны
Я бы проверил, если у вас есть проблемы с различными установками библиотек, которые вы используете. Например, вы ссылаетесь на libpqxx-4.0, но позже, когда вы запускаете программу, вы используете другую версию.
$ ldd client
linux-gate.so.1 => (0xb7776000)
libpqxx-4.0.so => не найден
libstdc ++. so.6 => /usr/lib/libstdc++.so.6 (0xb7669000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb764a000)
libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb7503000)
libpthread.so.0 => /lib/i686/cmov/libpthread.so.0 (0xb74ea000)
libm.so.6 => /lib/i686/cmov/libm.so.6 (0xb74c4000)
/lib/ld-linux.so.2 (0xb7777000)
Поскольку я скачал и установил libpqxx-4.0.1 вручную, я должен установить LD_LIBRARY_PATH
явно, так как я не установил его ниже /usr/local/
, Если разные версии установлены в /usr/local
Почисти там раньше.
В вашем случае (используя ldd
) libpqxx должен указывать на версию, которую вы скомпилировали и установили. Убедитесь, что в вашей системе установлен только один libpqxx.
Я использовал это Makefile
CPPFLAGS + = -I / home / dev / data / src / cpp / libpqxx-4.0.1 / install / include
LDFLAGS + = -L / home / dev / data / src / cpp / libpqxx-4.0.1 / install / lib -lpqxx -lstdc ++клиент: client.o
и libpqxx был построен с
./ configure —prefix = / home / dev / data / src / cpp / libpqxx-4.0.1 / install —enable-shared
делать
сделать установку
и я запустил программу, используя
LD_LIBRARY_PATH = $ LD_LIBRARY_PATH: /home/dev/data/src/cpp/libpqxx-4.0.1/install/lib client
Вероятно, что pqxx :: result вызывает утечку памяти. Попробуйте добавить:
r.clear();
Это по крайней мере уменьшит утечку.
#include <iostream>
#include <pqxx/pqxx>
#include <string>
#include <stdio.h>
int main()
{
try
{
pqxx::connection c("user=postgres");
int i = 0;
while(true)
{
pqxx::work w(c);
pqxx::result r = w.exec("SELECT 1");
i++;
if ( i % 1000 == 0 )
printf( "Cycle %d\n", i );
r.clear();
} //while
} //try
catch (const std::exception &e)
{
std::cerr << e.what() << std::endl;
return 1;
} //catch
} //main
Попробуйте объявить pqxx :: result r без пока. И звони внутрь, как делаешь. Потому что для каждого цикла while вы создаете объект pqxx :: result. Таким образом, вы создадите только один объект для всего цикла, чтобы заряжать и очищать в каждом цикле:
#include <iostream>
#include <pqxx/pqxx>
#include <string>
#include <stdio.h>
int main()
{
try
{
pqxx::connection c("user=postgres");
int i = 0;
pqxx::result r;
while(true)
{
pqxx::work w(c);
r = w.exec("SELECT 1");
w.commit();
i++;
if ( i % 1000 == 0 )
printf( "Cycle %d\n", i );
r.clear();
} //while
} //try
catch (const std::exception &e)
{
std::cerr << e.what() << std::endl;
return 1;
} //catch
} //main
Или, что еще лучше, создайте метод для вызова в каждом цикле while, поэтому после завершения каждого вызова метода временный объект исчезнет.
main()
{
...
while()
{
...
method_to_call_pqxx();
}
}