首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这个简单的libpqxx代码会泄漏内存?

为什么这个简单的libpqxx代码会泄漏内存?
EN

Stack Overflow用户
提问于 2013-07-02 17:41:51
回答 3查看 2.7K关注 0票数 4

最近,我编写了一个通过libpqxx访问Postgres的应用程序,它严重地泄漏了内存。甚至这个基于http://pqxx.org/devprojects/libpqxx/doc/4.0/html/Reference/a00001.html示例的简单测试程序也会泄漏,就像明天没有泄漏一样。

(编辑:为了响应建议,我添加了提交()和清除()的调用。同样的泄漏。)

代码语言:javascript
复制
#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

经过大约7.5万个循环之后,顶部显示了206 it的虚拟内存使用情况,并且还在不断上升。我运行了一个类似的测试程序,使用了5000次循环,并得到了如下结果:

代码语言:javascript
复制
==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这样被广泛使用的库会有如此严重的错误,那么我在这里可能做错了什么呢?

配置详细信息:

  • 操作系统:Linux2.6.18-238.el5
  • gcc 4.4.0版
  • libpqxx 4.0
  • postgres 9.2

(最终编辑:我发现用libpq替换libpqxx比继续调查这个内存泄漏()更容易。)

EN

回答 3

Stack Overflow用户

发布于 2013-07-03 08:32:26

我无法重现你的问题。

无论是libpqxx-2.6.9还是libpqxx-4.0.1 (目前的稳定版本)。

  • Debian Linux 2.6.32
  • gcc版4.4.5
  • libpq5 8.4.17
  • libpqxx 4.0.1
  • libstdc++ 6.4.4
  • postgres 8.4

内存使用情况是恒定的。

$ valgrind tool=memcheck run.sh ..。 周期35000 周期36000 ^C==18420== ==18420==堆摘要: 退出时使用的==18420==:0块中的0字节 ==18420==总堆使用率:0分配程序,0空闲,0字节分配 ==18420== ==18420==所有堆块都被释放了--没有泄漏的可能

我会检查,如果您使用的库的不同安装有问题。例如,您是否链接到libpqxx-4.0,但是稍后,当您运行程序时,您使用的是不同的版本。

$ ldd客户端 LinuxGate.so.1 => (0xb7776000) libpqxx-4.0因此找不到=> libstdc++.so.6 => /usr/lib/libstdc+.so.6 (0xb7669000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb764a000) libc.so.6 => /lib/i 686/cmov/libc.so.6 (0xb7503000) libpthread.so.0 => /lib/i 686/cmov/libpter.so.0 (0xb74ea000) libm.so.6 => /lib/i 686/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 += -L/home/dev/data/src/cpp/libpqxx-4.0.1/install/lib += -lpqxx -lstdc++客户端: client.o

而libpqxx是用

./配置--prefix=/home/dev/data/src/cpp/libpqxx-4.0.1/install --启用-共享 制作 制造安装

我运行了这个程序

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/dev/data/src/cpp/libpqxx-4.0.1/install/lib客户端

票数 3
EN

Stack Overflow用户

发布于 2013-07-02 18:00:10

很可能pqxx::result正在泄漏内存。试着添加:

代码语言:javascript
复制
r.clear();

至少可以减少漏水。

代码语言:javascript
复制
#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
票数 1
EN

Stack Overflow用户

发布于 2014-05-12 15:11:35

尝试声明pqxx::结果r白化时间。就像你现在做的那样,把它叫进去。因为对于时间的每一个周期,您都要创建一个pqxx::result对象。通过这种方式,您将只为所有循环创建一个对象,以便在每个循环中充电和清除:

代码语言:javascript
复制
#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的每个循环中调用,因此,当方法的每个调用完成时,tne临时对象就会消失。

代码语言:javascript
复制
main()
{
    ...
    while()
    {
        ...
        method_to_call_pqxx();
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17432242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档