メモリリークが発生します。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
jyun

メモリリークが発生します。

#1

投稿記事 by jyun » 17年前

ODBCを使用して抽出系SQLを発行し、結果を返却する関数を作成したのですが、
呼び出すたびにプログラムのメモリ消費量が上がり続けてしまいます。

実際のコードは別関数にてConnectとCloseがあり、Closeでは
SQLDisconnect( hdbc );
SQLFreeHandle( SQL_HANDLE_DBC, (SQLHANDLE)hdbc );
SQLFreeHandle( SQL_HANDLE_ENV, (SQLHANDLE)henv );
とコールして、解放しています。

プログラムは常駐型ですので、メモリリークするとまともに動かなくなってしまうので、
どうしても解消したいと考えています。
よろしくお願いします。

以下、見難いですがソースです。
// ユーザ定義型
typedef map<string, string> mapstr;
typedef vector<mapstr> vmap;

/*
 *  関数名  :  execSelect
 *  処理概要:  map<string, string>のvectorの抽出結果を返す。
 */
vmap execSelect(char* chrSelect){

    RETCODE             rc;
    mapstr              mapRet;
    vmap                vmapRet;
    vector<string>      colinfo;
    vector<char>        buff;
    SQLHSTMT            hstmt;

    rc = SQLAllocStmt(hdbc, &hstmt);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
        return vmapRet;
    }
    SQLSMALLINT sintcols = 0;

    char colname[128+1]; // カラム名
    SQLSMALLINT colnamelen = 0; // カラム名の文字数
    SQLSMALLINT coltype = 0; // データの型
    SQLUINTEGER collen; // このカラムの領域サイズ(バイト単位)
    SQLSMALLINT scale = 0; // たとえば,NUMERIC(10,3)なら, 3が入る。使われないことも多い
    SQLSMALLINT nullable = 0; // NULLが可能かどうか

    rc = SQLPrepare(hstmt, (SQLCHAR*)chrSelect, SQL_NTS);
    rc = SQLExecute(hstmt);

    SQLNumResultCols( hstmt, &sintcols);
    for (int intcnt = 0; intcnt < sintcols; intcnt++) {
        SQLDescribeCol(hstmt, (UWORD)(intcnt + 1), (SQLCHAR*)colname, (SWORD)sizeof(colname), &colnamelen, &coltype, &collen, &scale, &nullable);
        colname[128] = '\0';
        colinfo.push_back(string(colname));
    }

    for (rc=SQLFetch(hstmt); rc == SQL_SUCCESS; rc=SQLFetch(hstmt)) {
        SQLINTEGER      rbufsize = 0;
        for ( int i = 0; (size_t)i < colinfo.size(); i++ ) {
            buff.resize(128);
            rc = SQLGetData( hstmt, i+1, SQL_C_CHAR, &buff[0], (SQLINTEGER)buff.size(), &rbufsize);
            if ( rbufsize > (SQLINTEGER)buff.size() && rc == 1 ) {
                buff.clear();
                buff.resize(rbufsize);
                rc = SQLGetData( hstmt, i+1, SQL_C_CHAR, &buff[0], (SQLINTEGER)buff.size(), &rbufsize);
            }
            if ( rbufsize < 0 ) {
                // NULL は空文字にする
                buff[0] = '\0';
                rbufsize = 1;
            }
            mapRet[colinfo] = string(buff.begin(), buff.begin() + rbufsize);
        }
        vmapRet.push_back(mapRet);
        mapRet.clear();
    }

    // メモリの開放
    SQLFreeStmt(hstmt, SQL_DROP);
    return vmapRet;
}

jyun

Re:メモリリークが発生します。

#2

投稿記事 by jyun » 17年前

呼び元を書くのを忘れていました。

上記のソースはクラス化されており、
呼出元クラスのコンストラクタでnewしてデストラクタでdeleteしています。

メインは処理要求が発生するたびにスレッドを作成し、
作成されたスレッドが上述の呼出元クラスをnewし、処理が終わるとdeleteしています。

よろしくお願いします。

jyun

Re:メモリリークが発生します。

#3

投稿記事 by jyun » 17年前

自己解決しました。

抽出系SQLの場合でも最後にトランザクションの終了が必要みたいでした。
コミットを発行して終了するようにしたら解放されました。

閉鎖

“C言語何でも質問掲示板” へ戻る