You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用libpq的C程序中PQconnectdb相关内存泄漏问题求助

解决libpq连接PostgreSQL时Valgrind检测到的GSSAPI相关内存泄漏

你的代码本身没有内存管理错误,Valgrind报告的still reachable内存泄漏来自GSSAPI(Kerberos认证)相关的系统库,而非libpq的使用逻辑。以下是具体分析和解决方案:

泄漏原因分析

从Valgrind的调用栈可以看到,所有未释放的内存都来自libgssapi_krb5.so和libkrb5support.so的内部操作,这些是PostgreSQL连接时可能加载的认证/加密库。你已经正确调用了PQfinish(conn)(释放连接资源)和PQclear(res)(释放查询结果),代码层面没有问题。

Valgrind标记的still reachable类型泄漏,是指进程退出时内存仍可被访问但未被显式释放的情况。这类内存通常是库的全局缓存或初始化资源,进程结束后操作系统会自动回收所有内存,不会导致实际运行时的内存溢出或增长,属于无害的“假阳性”报告。

缓解方案

如果一定要消除Valgrind的这些报告,可以尝试以下两种方法:

1. 禁用GSSAPI认证/加密

在连接字符串中添加gssencmode=disable,强制libpq不加载GSSAPI相关库,从根源避免这类内存分配:

// 修改连接字符串为标准键值对格式
char conninfo[200] = "host=<HOST NAME> user=<USERNAME> password=<PASSWORD> gssencmode=disable";
PGconn *conn = PQconnectdb(conninfo);

注意:原代码中直接用strcat拼接<HOST NAME>、<USERNAME>、<PASSWORD>是错误的,正确的连接字符串需要是host=xxx user=xxx password=xxx的键值对格式,原写法会导致连接参数无效,建议修正为标准格式。

2. 使用Valgrind抑制文件

创建一个抑制文件(比如postgresql.supp),添加针对GSSAPI库的抑制规则,让Valgrind忽略这些预期的泄漏:

{
   <gssapi_leak>
   Memcheck:Leak
   match-leak-kinds: reachable
   fun:malloc
   ...
   obj:/usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2
}
{
   <krb5support_leak>
   Memcheck:Leak
   match-leak-kinds: reachable
   fun:malloc
   ...
   obj:/usr/lib/x86_64-linux-gnu/libkrb5support.so.0.1
}

运行Valgrind时指定该文件:

valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all -s --suppressions=postgresql.supp ./test

测试代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libpq-fe.h>

void exit_nicely(PGconn *conn){
    fprintf(stderr, "%s\n", PQerrorMessage(conn));
    PQfinish(conn);
    exit(1);
}

int main(int argc, char **argv){
    
    // 建立数据库连接(修正为标准键值对格式)
    char conninfo[200] = "host=<HOST NAME> user=<USERNAME> password=<PASSWORD>";
    PGconn *conn = PQconnectdb(conninfo);
    (PQstatus(conn) == CONNECTION_OK) ? printf("Connected\n") : exit_nicely(conn);
    
    // 发送查询并接收结果
    PGresult* res = PQexec(conn, "SELECT VERSION();");

    // 错误检查
    if(PQresultStatus(res) != PGRES_TUPLES_OK){
        fprintf(stderr, "ERROR%d: %s\n", PQresultStatus(res), PQresStatus(PQresultStatus(res)));
        PQclear(res);
        exit_nicely(conn);
    }
    
    // 从结果中提取数据
    printf("Attribute1 name: %-15s\n", PQfname(res, 0));
    printf("Attribute1, row1 value: %-15s\n", PQgetvalue(res, 0, 0));
    PQclear(res); 
 
    PQfinish(conn);
    return 0;
}

Valgrind输出结果

valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all -s ./test
==7827== Memcheck, a memory error detector
==7827== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7827== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==7827== Command: ./test
==7827== 
Connected
Attribute1 name: version        
Attribute1, row1 value: PostgreSQL 14.6 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
==7827== 
==7827== HEAP SUMMARY:
==7827==     in use at exit: 153 bytes in 4 blocks
==7827==   total heap usage: 33,923 allocs, 33,919 frees, 3,248,431 bytes allocated
==7827== 
==7827== 8 bytes in 1 blocks are still reachable in loss record 1 of 4
==7827==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7827==    by 0x4FEC4E9: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x50038A6: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x50043D9: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4FDE532: gss_add_cred_from (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4FE1187: gss_acquire_cred_from (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4FE13C9: gss_acquire_cred (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4878B73: PQconnectPoll (in /usr/lib/x86_64-linux-gnu/libpq.so.5.15)
==7827==    by 0x487A2EF: ??? (in /usr/lib/x86_64-linux-gnu/libpq.so.5.15)
==7827==    by 0x487A3E7: PQconnectdb (in /usr/lib/x86_64-linux-gnu/libpq.so.5.15)
==7827==    by 0x10949F: main (in /home/shawn/Lab4/test)
==7827== 
==7827== 24 bytes in 1 blocks are still reachable in loss record 2 of 4
==7827==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7827==    by 0x4FEC494: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x50038A6: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x50043D9: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4FDE532: gss_add_cred_from (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4FE1187: gss_acquire_cred_from (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4FE13C9: gss_acquire_cred (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4878B73: PQconnectPoll (in /usr/lib/x86_64-linux-gnu/libpq.so.5.15)
==7827==    by 0x487A2EF: ??? (in /usr/lib/x86_64-linux-gnu/libpq.so.5.15)
==7827==    by 0x487A3E7: PQconnectdb (in /usr/lib/x86_64-linux-gnu/libpq.so.5.15)
==7827==    by 0x10949F: main (in /home/shawn/Lab4/test)
==7827== 
==7827== 48 bytes in 1 blocks are still reachable in loss record 3 of 4
==7827==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7827==    by 0x517F6C4: krb5int_setspecific (in /usr/lib/x86_64-linux-gnu/libkrb5support.so.0.1)
==7827==    by 0x4FEC505: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x50038A6: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x50043D9: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4FDE532: gss_add_cred_from (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4FE1187: gss_acquire_cred_from (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4FE13C9: gss_acquire_cred (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4878B73: PQconnectPoll (in /usr/lib/x86_64-linux-gnu/libpq.so.5.15)
==7827==    by 0x487A2EF: ??? (in /usr/lib/x86_64-linux-gnu/libpq.so.5.15)
==7827==    by 0x487A3E7: PQconnectdb (in /usr/lib/x86_64-linux-gnu/libpq.so.5.15)
==7827==    by 0x10949F: main (in /home/shawn/Lab4/test)
==7827== 
==7827== 73 bytes in 1 blocks are still reachable in loss record 4 of 4
==7827==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7827==    by 0x496060E: strdup (strdup.c:42)
==7827==    by 0x4FEC456: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x50038A6: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x50043D9: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4FDE532: gss_add_cred_from (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4FE1187: gss_acquire_cred_from (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x5006629: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x5006749: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4FDE532: gss_add_cred_from (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4FE1187: gss_acquire_cred_from (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827==    by 0x4FE13C9: gss_acquire_cred (in /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2)
==7827== 
==7827== LEAK SUMMARY:
==7827==    definitely lost: 0 bytes in 0 blocks
==7827==    indirectly lost: 0 bytes in 0 blocks
==7827==      possibly lost: 0 bytes in 0 blocks
==7827==    still reachable: 153 bytes in 4 blocks
==7827==         suppressed: 0 bytes in 0 blocks
==7827== 
==7827== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

内容的提问来源于stack exchange,提问作者Shawn Armstrong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 07:05:20