FindFile()によるメモリ増加現象

[戻る]
野球小僧 2005/08/04(木) 00:06:49
CFileFindクラスのメンバ関数である、CFileFind.FindFile()を実行していくと、
仮想メモリ及び物理メモリが増加して行きます。
(念のため、APIであるFirstFind()でも同様)
CFileFindクラスのデストラクタもしくは、同メンバ関数のCFileFind.Close()
で後処理を実施していても現象は改善されません。
長期間連続稼動状態が続くとアプリケーションエラーが発生すると思われます。
(負荷試験を実施したら数日でアプリケーション異常発生)

定期的に、アプリケーションをリセットするしか方法はないのでしょうか?
(当該関数を使用することは絶対条件です。)

「開発環境」
OS:Windows2000/WindowsXP(SP2)
コンパイラ:VisualStudio6.0(SP6)

ars 2005/08/04(木) 01:13:09
その部分のソースを出してもらえますか?
たぶん原因は他にある

野球小僧 2005/08/04(木) 08:05:51
製品向けプログラム中から、メモリ増加の原因が、FindFile()にあると
判断した際に、検証用に使用したコードを取急ぎ添付致します。
(別途、実際のコードも記載致します。)


パターン1
{
  CString   cStringFileName="c:\\Test\\*.*";
  CFileFind cFileFind;

  for( int iLoop=0; iLoop<100; iLoop++ )
  {
    cFileFind.FindFile( cStringFileName, 0);
    cFileFind.Close();
  }
}

パターン2
{
  CString   cStringFileName="c:\\Test\\*.*";

  for( int iLoop=0; iLoop<100; iLoop++ )
  {
   CFileFind cFileFind;
    cFileFind.FindFile( cStringFileName, 0);
  }
}

wish 2005/08/04(木) 09:58:11
はじめまして。
CFileFindは使ったこと無いであまりいい加減なことはいえませんが、
こんな感じではどうでしょうか^^;
if( filefind.FindFile(mych1) ) { 
   do { 
    b = filefind.FindNextFile();
   } while( b );
filefind.Close(); 
  } 


注意
このプログラムだと100個検索したら終わりますので全部のファイル検索する場合は
FindNextFileの戻り値を使用して戻り値はBOOLなので簡単に使えると思います

wish 2005/08/04(木) 09:58:11
はじめまして。
CFileFindは使ったこと無いであまりいい加減なことはいえませんが、
こんな感じではどうでしょうか^^;
if( filefind.FindFile(mych1) ) { 
   do { 
    b = filefind.FindNextFile();
   } while( b );
filefind.Close(); 
  } 


注意
このプログラムだと100個検索したら終わりますので全部のファイル検索する場合は
FindNextFileの戻り値を使用して戻り値はBOOLなので簡単に使えると思います

wish 2005/08/04(木) 10:01:18
うわ。。。連続投稿に。。。;
インデントぐちゃぐちゃですみません。。。;

CString   cStringFileName="c:\\Test\\*.*";
CFileFind cFileFind;
bool ret;

if( cFileFind.FindFile(cStringFileName) ) { 
   do { 
       ret = cFileFind.FindNextFile();
   } while( ret );
   cFileFind.Close(); 
} 

お邪魔しました。。。;

επιστημη [E-Mail] 2005/08/04(木) 10:20:26
VC++7.1で追試しました。

100万回ループさせましたが、実行中メモリ使用量は一定、
右肩上がりに上昇「しません」。

VC++6ならではの現象? 
だとすると Win32-APIでもそうなる理由がないな…

επιστημη [E-Mail] 2005/08/04(木) 10:22:14
> CFileFindは使ったこと無いであまりいい加減なことはいえませんが、
> こんな感じではどうでしょうか^^;
> .....

これのどこが "メモリ食いつぶし" の対策になってんですか?

野球小僧 2005/08/04(木) 10:25:37
上記サンプルコードの主旨を誤解されているようなので、注記させて下さい。
上記サンプルコードは、FindFile()/FindNextFile()の使い方を皆さんにご教授頂きた
く記載したものではございません。

ファイル検索処理は、皆さんから示された方法を使用しております。。
FindFile()を実行すると、実行回数に比例して、メモリ使用量が増加して行く現象を
手っ取り早く、ご確認頂く為に作成したコードでございます。

当然、皆さんからご教授頂いております方法においてもこの処理を
連続的に実行させていけば、メモリ使用量が増加して行きます。

これが、マイクロソフトの不具合であれば、
FindFile()を使用している限りは、定期的にアプリをリセットするとかの
運用方法でカバーしなくてはならないと思っております。

マイクロソフトの技術情報では、過去事例など検索しても見当たらなかったので、
回避する手段とうお分かりになられている方がいらっしゃいましたら、
アドバイス願います。

επιστημη [E-Mail] 2005/08/04(木) 10:35:24
> 当然、皆さんからご教授頂いております方法においてもこの処理を
> 連続的に実行させていけば、メモリ使用量が増加して行きます。

あれー? 100万回じゃ足りませんか?
目下一億回のループを回してますが、
メモリを食いつぶす気配が感じられないんすけど…

野球小僧 2005/08/04(木) 10:47:26
To επιστημηさんへ
検証ありがとうございます。
やはり、当方の環境下におきましては、タスクマネージャーのプロセスタブの
当該プロセスのメモリ使用量が、100回の実施に付き4kbyteづつ増加し続けます(><)
Windows2000でコンパイラ環境は同様のマシンで実施しても同一現象が発生。。。
当方も、.Netの環境で実施させて見ます。。

Mell 2005/08/04(木) 10:48:27
野球小僧さんのサンプルのように100回程度ループして1回目と100回目でメモリ使
用量が違うっていう程度では、リークとは断定できないんじゃないでしょうか?
検証用のプログラム全部と、どのように計測してリークと判断しているのかを示されたほ
うがいいと思いますが...

wish 2005/08/04(木) 10:59:43
すみません。かなり勘違いしてました。
わたしも先ほど100万回ループさせてみました
環境は OS:XPSP2 VC++6.0Pですが
提示されたプログラムでは実行中メモリ使用量は一定、
上昇しませんでした。

ちなみに私がかいたプログラムのほうは、エラーっぽいですね^^;

Mell 2005/08/04(木) 11:15:19
> 当該プロセスのメモリ使用量が、100回の実施に付き4kbyteづつ増加し続けます(><)

私も検証。
パターン1(100ループ)をそのまま 1万回ループさせてみて、合計 100万回実行してみま
したが、その間、メモリ使用量は約 1.6MB, 仮想メモリサイズは約 550KB くらいで一定
していました。

OS:WindowsXP(SP2)
コンパイラ:VisualStudio6.0(SP6)

CWinApp theApp;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0);

    for (int i = 0; i < 10000; i++)
    {
      CString   cStringFileName="c:\\Test\\*.*";
      CFileFind cFileFind;

      for( int iLoop=0; iLoop<100; iLoop++ )
      {
        cFileFind.FindFile( cStringFileName, 0);
        cFileFind.Close();
      }
    }
    puts("end");
    getchar();

    return 0;
}

野球小僧 2005/08/04(木) 12:00:37
To Mellさんへ
実際に検証した方法としては、FindFile()/FindNextFile()の処理を実装している
アプリケーションで、本処理が、1回/1秒の割合で実行する負荷試験を行った結果
5日間で、メモリーリークが発生しました。
擬似的に、本処理をマスク(コメント)した状態で負荷試験を行った場合は、
メモリは安定しており、メモリリークは発生しませんでした。
このような経緯を経て、本処理に着目した結果メモリが解放されていないため、
おかしいと判断して、皆さんにお尋ねした次第です。

当方でも同僚の協力で、様々な環境下で実施した結果です。

★WindowsXP(SP1)/VisualStudio6(SP6)(本機にはVisualStudio7.1もある)→非再現
★WindowsXP(SP2)/VisualStudio6(SP6)(本機にはVisualStudio7.1はない)→再現
★Windows2000/VisualStudio6(SP6)(本機にはVisualStudio7.1はない)→再現
★WindowsXP(SP1)/VisualStudio7.1→非再現
★WindowsXP(SP2)/VisualStudio7.1→非再現

今のところ、VisualStudio6(SP6)のみを搭載した環境で再現している傾向があると
思われます。(もう少し、多種に渡り継続調査します。)

Mellさんの実行環境下には、VisualStudio7.1(.Net2003)はインストールされておりませ
んか??

επιστημη [E-Mail] 2005/08/04(木) 12:38:37
確認ですが、Win32-API: FindFirstFile/FineNextFile/FindCloseに
置き換えても再現しますか? 
もしそうなら、VC++/MFCのバージョンとは関係ないことになります。

野球小僧 2005/08/04(木) 12:56:18
To επιστημηさんへ

API使用時のサンプルコードです。やはり結果は同じですね。。。。

#include "io.h"

サンプル関数()
{
 int    iCounter=0;
  CString     cStringFileName="c:\\test\\*.*";

  for( int iLoop=0; iLoop<100; iLoop++ )
  {
    long    handle;
    struct  _finddata_t  fd;

    handle = _findfirst(cStringFileName, &fd);
        
    if( handle != (-1) )
    {
      iCounter = 0;

      do
      {
    TRACE("%d\n",iCounter++ );
      }
      while(_findnext(handle, &fd) == 0);

      _findclose( handle );
    }
 }
}

REE 2005/08/04(木) 13:30:37
Mellさんのコードでやってみました。

★WindowsXP(SP1)/VisualStudio6(SP6)(本機にはVisualStudio7.1はない)→非再現

a 2005/08/04(木) 13:32:25
プログラムやAPIが原因がではなく
その他の常駐アプリ(アンチウィルスソフト)等が悪さしてるとか・・・

επιστημη [E-Mail] 2005/08/04(木) 13:50:11
#include <windows.h>
#include <stdio.h>

int main() { 
  const char* name ="d:\\work\\*.*";
  for( int iLoop=0; iLoop<1000000; iLoop++ ) {
    WIN32_FIND_DATA fd;
    HANDLE handle = FindFirstFile(name, &fd);
    if( handle != INVALID_HANDLE_VALUE ) {
      int iCounter = 0;
      do {
        printf("%d ", iCounter++);
      } while( FindNextFile(handle, &fd) );
      FindClose(handle);
      puts("");
    }
  }
}

処理系/ライブラリの影響を排除すべく、DigitalMars C++ でコンパイルしました。

★Windows2000→非再現

Mell 2005/08/04(木) 16:16:56
>Mellさんの実行環境下には、VisualStudio7.1(.Net2003)はインストールされておりませ
んか??

インストールされています。
念のため、VC++ 開発環境が一切入っていない WindowsXP(SP2) および Windows2000(SP4)
の環境でも同じプログラムを実行してみましたが問題は再現していません。
※前回のは実機で、今回試した環境は Virtual PC ゲストマシンです。

古いスレッドには追加発言できません。