ADOConnection.ExecuteでOracle.exeがメモリーリークする – プログラミング – Home

通知
すべてクリア

[解決済] ADOConnection.ExecuteでOracle.exeがメモリーリークする


MoonFull
 MoonFull
(@MoonFull)
ゲスト
結合: 14年前
投稿: 4
Topic starter  

開発環境
OS:WindwosXP SP3
VC++6.0
Oracle 10.2.0.1
MDAC 2.81.1132.0

上記環境でADOでDBの書込み処理を行うと、
Oracle.exeがメモリーリークを起こしてしまいます。

以下ソースの抜粋です。

void CxxxDlg::DbOpen()
{
::CoInitialize(NULL);

_ConnectionPtr m_AdoCon;// ADOコネクトオブジェクト

hr = m_AdoCon.CreateInstance(__uuidof(Connection));
m_AdoCon->CursorLocation = (enum CursorLocationEnum)3;//クライアントサイドカー
ソル

hr = m_AdoCon->Open(Provider=MSDAORA;CONNECTSTRING=XXX;User
Id=XXX;Password=XXX, ", ", adConnectUnspecified);
}

void CxxxDlg::ExecuteSQL(LPCTSTR szSQL)
{
long lOption = adCmdText;
BSTR bstrQuery;
bstrQuery = NULL;
char* psz = new char[2048];
::memset(psz,0,sizeof(psz));

wsprintf(psz,szSQL);
bstrQuery = _com_util::ConvertStringToBSTR(psz);
m_AdoCon->Execute( bstrQuery ,NULL,lOption);

SysFreeString(bstrQuery);
delete [] psz;
}

void DbClose()
{
m_AdoCon->Close();
m_AdoCon= NULL;

::CoUninitialize();
}
----------------------------------------------

DBOpen後、ExecuteSQL関数でテーブルのInsert,Update,Deleteを
レコード1件ずつ行っています。
1000件Insertする場合は1000回呼ばれます。
ループを繰り返すと、アプリのメモリは変わらず、
Oracle.exeのメモリが上昇します。

何故メモリーがリークするのか、解決方法がありましたら、ご教授願います。

よろしくお願いいたします。


引用未解決
トピックタグ
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

以下の二点に関して疑問を感じます。

・メモリが上昇すると言うのは何を根拠に書いているのか。

・メモリの使用量が上昇すると言う意味だとしてその事が
 そのままメモリリークしていると言う事になるのか。

adoを使わなければ、同等と思われる処理を行っても
Oracle.exeのメモリ使用量は上昇しないのでしょうか?

その辺りの話も気になりますね。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

まず、
 ・デバッグモードで実行してリークすると思うタイミングで終了する。
 ・表示されないときもあるみたいですが、メモリーリークすると「Memory Leak」
  というようなコメントが表示される。
ですね。

「Memory Leak」のコメント以降の表示をここに公開すると何か回答が出来るかも知れま
せん。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

ん?、
 Connectと自作のExecuteSQL関数が終了したことを確かめて、から次の処理を実行して
いま
すか?
特に、自作のExecuteSQL関数で、「new」「delete」の処理をしているのが気になります
ね。


返信引用
MoonFull
 MoonFull
(@MoonFull)
ゲスト
結合: 14年前
投稿: 4
Topic starter  

PATIOさん、ITOさん返信ありがとうございます。

> ・メモリが上昇すると言うのは何を根拠に書いているのか。
>
> ・メモリの使用量が上昇すると言う意味だとしてその事が
>  そのままメモリリークしていると言う事になるのか。

1000件レコードを1件ずつInsertして、その1000件を1件ずつDeleteするというループ処
理を延々とやっています。
すると、Oracle.exeが2GBまで上昇し、その後、DB書込みエラーとなります。

> adoを使わなければ、同等と思われる処理を行っても
> Oracle.exeのメモリ使用量は上昇しないのでしょうか?

adoを使わない場合、oo4oのODynaSetを使用して書込みを行うとメモリは上昇しません。
また、今回のソースはSQLSeverにAODで接続してる別のアプリを参考に作成してるのです
が、そっちのADOConnection.Executeではメモリが上昇していません。

>  Connectと自作のExecuteSQL関数が終了したことを確かめて、から次の処理を実行し
> ていま
> すか?
> 特に、自作のExecuteSQL関数で、「new」「delete」の処理をしているのが気になりま
> すね。

ConnectのOpenとCloseはアプリ起動時と終了時に行っています。
シングルスレッドで行っているためExecuteSQL関数が終了してから次のExecuteSQL関数
を呼んでいます。
また、アプリのメモリ使用量は増えていない為、、「new」「delete」での解放漏れ等は
ないと考えています。


返信引用
bun
 bun
(@bun)
ゲスト
結合: 24年前
投稿: 761
 

気になるのが、ConnectのOpenとCloseをループ中でやってみるとどうなるか?
それで解決するようなら、ループ中に必要な処理が何か抜けています。

メモリリークとは微妙に違う、メモリパンクではないかと推測します。

例えば、CFileクラスには CFile::Flush() というメンバがいます。
Flush()せずに書き込みまくれば、バッファがパンクするわけです。

同様に、Connection::Execute()に対しても、Flush()のような
ものが存在するのではないかと。
それが何かは分かりませんでしたが、Close() & Open() なら結果として同様の
ことが起きるので問題解決するのでは?ということです。

ただ、いちいちClose() & Open() だと遅そうなので、
Flush()に当たるものを探すことをお勧めします。


返信引用
しま
 しま
(@しま)
ゲスト
結合: 18年前
投稿: 123
 

>1000件レコードを1件ずつInsertして、その1000件を1件ずつDeleteするという
>ループ処理を延々とやっています。
>すると、Oracle.exeが2GBまで上昇し、その後、DB書込みエラーとなります。

オラクルのメモリー使用量が増加するのはどのようにして確認しているか
書いたほうが読む人に親切だと思います
それと、メモリーの使用量が増加するというだけではメモリーリークだと
決めらないと思いますよ

ところでトランザクションは行っていますか?

以下のページは参考になりますか?
http://support.microsoft.com/kb/198024/ja


返信引用
MoonFull
 MoonFull
(@MoonFull)
ゲスト
結合: 14年前
投稿: 4
Topic starter  

bunさん、しまさん返信ありがとうございます。

> 気になるのが、ConnectのOpenとCloseをループ中でやってみるとどうなるか?

試してみたところ、メモリの増加しませんでした。
最低限の処理として使えそうです。
ありがとうございます。
CFile::Flush()にあたるものを調査してみたいと思います。

> オラクルのメモリー使用量が増加するのはどのようにして確認しているか
> 書いたほうが読む人に親切だと思います

リークの調査はパフォーマンスモニタで、Oracle.exeのPage File Bytesで確認していま
す。

> ところでトランザクションは行っていますか?

今回の処理ではトランザクションは行っていません。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

オラクルから見たらきちんと処理した結果、メモリの開放タイミングがない為に
メモリが開放されずに増え続けて最終的にオラクル側で処理できない状態になっているの
であれば、これはメモリリークとは言わないと思います。

メモリリークと言うのは内部で管理して開放されるべきタイミングで開放されていない状
況を指すわけで、外部からの指示が無いと開放できない場合はこれに当たりません。
ですから、単純にメモリの使用量が増え続けると言うだけでメモリリークとはいえないわ
けです。
オラクルを使う側の使い方に問題がある場合、オラクルのメモリリークとは言いません。

意識してトランザクションを使っていなくてもOpen時にトランザクションスタートされて
いたりしませんかね。
話を聞いている限りではADOの中で何かやっているのではないかと言う気がします。
なんとなく、トランザクションが溜まりすぎてエラーとかそういう挙動に似ている気がし
ますけれど。

単純にメモリリークと書いてしまうとオラクルの不具合みたいに聞こえますから
言葉の使い方の問題ですけれど、気をつけた方が良いと思います。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

ちょっと日本語が変なので補足。

> メモリリークと言うのは内部で管理して開放されるべきタイミングで開放されて
> いない状況を指すわけで、

メモリリークと言うのは内部で管理されているメモリが解放されるべきタイミングで
解放されていない状況を指すわけで。

うっ、開放ではなくて解放ですね。
読み替えてください。(^^;


返信引用
MoonFull
 MoonFull
(@MoonFull)
ゲスト
結合: 14年前
投稿: 4
Topic starter  

> オラクルから見たらきちんと処理した結果、メモリの開放タイミングがない為に
> メモリが開放されずに増え続けて最終的にオラクル側で処理できない状態になってい
> るの
> であれば、これはメモリリークとは言わないと思います。

メモリの上昇 = メモリーリーク
という認識でいました。以後改めたいと思います。
ご指摘ありがとうございます。

とりあえず、bun さんにアドバイスしていただいたとおりに
Connect::Execute()時、毎回Open Closeするということで対応することになりましたの

これで解決としたいと思います。

皆々様、本当にありがとうございました。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

 解決済みですが、ODBC-SDKを使ったときはドライバーのエラーを見るコマンドが
ありました。
 ADOはないでしょうか?
 オラクルのメモリー使用量が上昇するぐらいですから何かエラーステータスでていて
もおかしくないです。
 昔調べてみた記憶だと、オラクルのエラーは皆英語です。
 


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました