GBase 8s
性能调优
文章

发现了一个ODBC gbase8s内存泄漏问题 确认一下

发表于2024-11-28 20:10:26222次浏览7个评论

void testgbase8s()
{
    //根据db_type构造gbase连接字符串
    SQLHENV hEnv = NULL;
    SQLHDBC hDbc = NULL;
    SQLRETURN retcode;

    // 分配环境句柄
    SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
    // 设置环境属性
    SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
    // 分配连接句柄
    SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);

    // 连接字符串
    SQLCHAR *connString = (SQLCHAR*)"DRIVER=/opt/GBASE/gbase/lib/cli/iclit09b.so;DLOC=zh_CN.57372;TDLL=/opt/GBASE/gbase/lib/esql/igo4a304.so;SKIPP=1;HOST=10.16.11.8;SERV=9088;SRVR=gbase01;DB=testdb;UID=dbtuser;PWD=GBase123$%;";
    retcode = SQLDriverConnect(hDbc, NULL, (SQLCHAR *)(connString), SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);

    if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
        cout << "Connected to the database successfully!" << endl;
    }
    else {
        cout << "Failed to connect to the database!" << endl;
        printError11(SQL_HANDLE_DBC, hDbc);

    }
    nlohmann::json row;

    std::string selectsql = "SELECT t1.tabname,t2.* FROM gbasedbt.systables t1 INNER JOIN gbasedbt.syscolumnsext t2 ON t1.tabid = t2.tabid WHERE t1.tabname = 'audit_log'";


    SQLHSTMT hstmt;
    int rc = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hstmt);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
    {
        std::cout << "hstmt error" << std::endl;
    }
    //selectsql = "SELECT * FROM newtable;";
    SQLExecDirect(hstmt, (SQLCHAR*)(selectsql.c_str()), SQL_NTS);


    //// 从结果集中获取数据


    while (SQLFetch(hstmt) != SQL_NO_DATA)
    {
        CHAR buffer[1024] = { 0 };
        nlohmann::json row;
        SQLSMALLINT columnCount;
        SQLRETURN cc = SQLNumResultCols(hstmt, &columnCount);
        SQLRETURN retcode;
        SQLCHAR Sqlstate[6], Message[SQL_MAX_MESSAGE_LENGTH];
        SQLINTEGER NativeError;
        SQLSMALLINT TextLength;
        for (SQLUSMALLINT i = 0; i < columnCount; ++i)
        {
            CHAR columnName[32] = { 0 };
            SQLSMALLINT nameLen = 0;
            SQLRETURN sqlret = SQLColAttribute(hstmt, i + 1, SQL_COLUMN_LABEL, columnName, sizeof(columnName), &nameLen, NULL);
            if (sqlret == SQL_ERROR)
            {
                retcode = SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, 1, Sqlstate, &NativeError, Message, sizeof(Message), &TextLength);
                if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
                    std::cout << "SQLSTATE: " << Sqlstate << std::endl;
                    std::cout << "Native Error: " << NativeError << std::endl;
                    std::cout << "Message: " << Message << std::endl;
                }
            }
            if (SQLGetData(hstmt, i + 1, SQL_C_CHAR, buffer, sizeof(buffer), NULL) == SQL_SUCCESS)
            {
                printf("columnName=%s,buffer=%s", columnName, buffer);
                if (strcasecmp(columnName, "colname") == 0)
                {
                    row["field"] = buffer;

                }
                else if (strcasecmp(columnName, "coltypename") == 0)
                {
                    row["type"] = buffer;

                }
                else if (strcasecmp(columnName, "collength") == 0)
                {
                    row["size"] = buffer;

                }


            }
        }
    }
    SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
    // 5. 关闭连接
    SQLDisconnect(hDbc);
    // 6. 释放连接句柄
    SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
    // 7. 释放环境句柄
    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
}

 

int main()
{
    for (int i = 0; i < 1; i++)
    {
        printf("第%d次连接", i);
        testgbase8s();
    }
    return 0;

}

 

SQLColAttribute申请的堆内存没有释放  循环调用testgbase8s()  内存会一直增大   /opt/GBASE/gbase/lib/cli/iclit09b.so  是咱们官网提供的clientsdk安装的   请帮忙看看我这么调用是不是有问题  还是你们的模块里有内存泄漏

评论

登录后才可以发表评论
用户头像
曾阿牛发表于 1年前
我们尽快确认
GBase用户16654发表于 1年前
@曾阿牛:有结果了吗
GBase用户16654发表于 1年前
14天了 有结果了吗 曾阿牛啊
BetterHan发表于 1年前
您好,使用您提供的代码。改写为c后复现了问题。

#include
#include
#include

#ifndef NO_WIN32
#include
#include
#include
#endif /*NO_WIN32*/

#include "infxcli.h"
#include "dbcreate.h"

#define ERRMSG_LEN 200

SQLCHAR defDsn[] = "odbc_demo";




void printError(SQLSMALLINT handleType, SQLHANDLE handle) {
SQLCHAR sqlState[1024];
SQLCHAR message[1024];
SQLINTEGER nativeError;
SQLRETURN ret = SQLGetDiagRec(handleType, handle, 1, sqlState, &nativeError, message, sizeof(message), NULL);
if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
//cout << "SQLSTATE: " << sqlState << endl;
//cout << "Message: " << message << endl;
printf("SQLSTATE: %d\n", sqlState);
printf("Message: %d\n", message);
}
}

void testgbase8s()
{
//根据db_type构造gbase连接字符串
SQLHENV hEnv = NULL;
SQLHDBC hDbc = NULL;
SQLRETURN retcode;

// 分配环境句柄
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
// 设置环境属性
SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
// 分配连接句柄
SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);

// 连接字符串
//SQLCHAR *connString = (SQLCHAR*)"DRIVER=/gbase8s/3.3.0_2X4_1/ids/lib/cli/iclit09b.so;DLOC=zh_CN.utf8;TDLL=/gbase8s/3.3.0_2X4_1/ids/lib/esql/igo4a304.so;HOST=172.16.5.202;SERV=10224;SRVR=ol_gbasedbt1210_20240718181816;DB=hyqdb;UID=gbasedbt;PWD=Big4ifmx;";
SQLCHAR *connString = (SQLCHAR*)"DRIVER=/gbase8s/3.3.0_2X4_1/ids/lib/cli/iclit09b.so;TDLL=/gbase8s/3.3.0_2X4_1/ids/lib/esql/igo4a304.so;HOST=172.16.5.202;SERV=10224;SRVR=ol_gbasedbt1210_20240718181816;DB=hyqdb;UID=gbasedbt;PWD=Big4ifmx;";
retcode = SQLDriverConnect(hDbc, NULL, (SQLCHAR *)(connString), SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);

//cout << retcode << endl;
printf("retcode = %d\n", retcode);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
//cout << "Connected to the database successfully!" << endl;
printf("Connected to the database successfully!\n");
}
else {
//cout << "Failed to connect to the database!" << endl;
printf("Failed to connect to the database!\n");
printError(SQL_HANDLE_DBC, hDbc);

}
// nlohmann::json row;

//std::string selectsql = "SELECT * from tt;";
char *selectsql = "SELECT * from tt;";


SQLHSTMT hstmt;
int rc = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hstmt);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
//std::cout << "hstmt error" << std::endl;
printf("hstmt error\n");
}
//selectsql = "SELECT * FROM newtable;";
SQLExecDirect(hstmt, (SQLCHAR*)(selectsql), SQL_NTS);


//// 从结果集中获取数据


while (SQLFetch(hstmt) != SQL_NO_DATA)
{
CHAR buffer[1024] = { 0 };
// nlohmann::json row;
SQLSMALLINT columnCount;
SQLRETURN cc = SQLNumResultCols(hstmt, &columnCount);
SQLRETURN retcode;
SQLCHAR Sqlstate[6], Message[SQL_MAX_MESSAGE_LENGTH];
SQLINTEGER NativeError;
SQLSMALLINT TextLength;
SQLUSMALLINT i;
for (i = 0; i < columnCount; ++i)
{
CHAR columnName[32] = { 0 };
SQLSMALLINT nameLen = 0;
SQLRETURN sqlret = SQLColAttribute(hstmt, i + 1, SQL_COLUMN_LABEL, columnName, sizeof(columnName), &nameLen, NULL);
if (sqlret == SQL_ERROR)
{
retcode = SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, 1, Sqlstate, &NativeError, Message, sizeof(Message), &TextLength);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
//std::cout << "SQLSTATE: " << Sqlstate << std::endl;
//std::cout << "Native Error: " << NativeError << std::endl;
//std::cout << "Message: " << Message << std::endl;
printf("SQLSTATE: %s\n", Sqlstate);
}
}
if (SQLGetData(hstmt, i + 1, SQL_C_CHAR, buffer, sizeof(buffer), NULL) == SQL_SUCCESS)
{
printf("columnName=%s,buffer=%s", columnName, buffer);
if (strcasecmp(columnName, "colname") == 0)
{
// row["field"] = buffer;

}
else if (strcasecmp(columnName, "coltypename") == 0)
{
// row["type"] = buffer;

}
else if (strcasecmp(columnName, "collength") == 0)
{
// row["size"] = buffer;

}


}
}
}
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
// 5. 关闭连接
SQLDisconnect(hDbc);
// 6. 释放连接句柄
SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
// 7. 释放环境句柄
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
}



int main()
{
int i = 0;
for (i = 0; i < 1; i++)
{
//printf("第%d次连接", i);
testgbase8s();
}
return 0;

}

编译:
gcc -c -fsigned-char -DNO_WIN32 -O -I/gbase8s/3.3.0_2X4_1/ids/incl/cli -I/gbase8s/3.3.0_2X4_1/ids/incl/esql -I/gbase8s/3.3.0_2X4_1/ids/incl/dmi dbcreate.c
gcc -o dbcreate dbcreate.o -L/gbase8s/3.3.0_2X4_1/ids/lib/cli -L/gbase8s/3.3.0_2X4_1/ids/lib/esql -lifcli -lifdmr -L/gbase8s/3.3.0_2X4_1/ids/lib/esql -lifgls -lifglx -lm -lnsl

运行:

valgrind --tool=memcheck --leak-check=yes ./dbcreate

问题展示:
Connected to the database successfully!
columnName=c1,buffer=1==25799==
==25799== HEAP SUMMARY:
==25799== in use at exit: 18,399,127 bytes in 1,473 blocks
==25799== total heap usage: 2,207 allocs, 734 frees, 19,516,096 bytes allocated
==25799==
==25799== 8 bytes in 1 blocks are definitely lost in loss record 101 of 283
==25799== at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==25799== by 0x4EFCBD9: __SQLColAttributeW (in /gbase8s/3.3.0_2X4_1/ids/lib/cli/libifcli.so)
==25799== by 0x4EFE896: SQLColAttribute (in /gbase8s/3.3.0_2X4_1/ids/lib/cli/libifcli.so)
==25799== by 0x400C13: testgbase8s (in /gbase8s/3.3.0_2X4_1/ids/demo/cli/dbcreate)
==25799== by 0x400D25: main (in /gbase8s/3.3.0_2X4_1/ids/demo/cli/dbcreate)
==25799==
==25799== LEAK SUMMARY:
==25799== definitely lost: 8 bytes in 1 blocks
==25799== indirectly lost: 0 bytes in 0 blocks
==25799== possibly lost: 0 bytes in 0 blocks
==25799== still reachable: 18,399,119 bytes in 1,472 blocks
==25799== suppressed: 0 bytes in 0 blocks
==25799== Reachable blocks (those to which a pointer was found) are not shown.
==25799== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==25799==
==25799== For counts of detected and suppressed errors, rerun with: -v
==25799== Use --track-origins=yes to see where uninitialised values come from
==25799== ERROR SUMMARY: 514 errors from 58 contexts (suppressed: 0 from 0)
BetterHan发表于 1年前
@BetterHan:头文件的地方没有贴出来,如下:
#include
#include
#include

#ifndef NO_WIN32
#include
#include
#include
#endif /*NO_WIN32*/
BetterHan发表于 1年前
@BetterHan:被过滤掉了。
用户头像
levvel发表于 6个月前
学习一下