メモリリークが発生します。
Posted: 2008年8月27日(水) 18:39
ODBCを使用して抽出系SQLを発行し、結果を返却する関数を作成したのですが、
呼び出すたびにプログラムのメモリ消費量が上がり続けてしまいます。
実際のコードは別関数にてConnectとCloseがあり、Closeでは
SQLDisconnect( hdbc );
SQLFreeHandle( SQL_HANDLE_DBC, (SQLHANDLE)hdbc );
SQLFreeHandle( SQL_HANDLE_ENV, (SQLHANDLE)henv );
とコールして、解放しています。
プログラムは常駐型ですので、メモリリークするとまともに動かなくなってしまうので、
どうしても解消したいと考えています。
よろしくお願いします。
以下、見難いですがソースです。
呼び出すたびにプログラムのメモリ消費量が上がり続けてしまいます。
実際のコードは別関数にて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;
}