■No30306 (Azulean さん) に返信
ソースの内容を付けられなくてすみません。
> どんなクラスかは分かりませんが、マネージオブジェクトはすぐにメモリ領域を解放しません。
> その前提を踏まえても、おかしいと思える動作だったということでしょうか?
説明が前後してしまうかもしれませんが、メモリ状況の把握は、System.Diagnostics.Process.GetCurrentProcess().PagedMemorySize64で値を取得して確認しています。
GC.Collect()すると、ガベージコレクトされる対象となり、ある程度メモリが溜まったら解放されるという認識でいます。
実際、メモリ圧迫していないクラスでは、PagedMemorySize64で取得した値がfor分を何回回しても一定の値で保たれています。
しかし、今回のクラスではメモリが延々増え続け、最後にはプログラムが落ちてしまうという状況になってしまいます。
> できれば、簡単なサンプルを示して頂ければ、どこに問題があるか指摘ができる可能性があります。
> サンプルができなくとも、そのクラスでどんなメモリ確保・リソース確保が行われているか、デストラクタ・ファイナライザで何かやってるかといった情報が寄せられれば、回答しやすいかと思います。
> # 例外でDisposeされていない(C++/CLIならdeleteか)ということはないと思いますが、念のため。
問題のクラスは、コンストラクタでログ出力の設定を行っています。
ログ出力機構はネイティブなC++で作成されたものを使用しています。
Singletonパターンを利用したログ出力機構です。
クラスライブラリと同じフォルダ内に指定したログ設定用ファイルがない場合はログを吐き出さないような仕組みしています。
ちょっと複雑な機構なので、概略で申し訳ないですが下記に記載させていただきます。
下記のようにして、DisposeにもGCにも対応可能にしています。
なお、後始末関係も二重の後始末が起きないようにケアしてあります。
// マネージドクラス
public ref class Klass
{
public:
//コンストラクタ
Klass()
{
//ログ出力の準備をする
try
{
ReadSettingFile readSettingFile;
readSettingFile.readSettingFile();
}
catch(MyException&)
{
//いろいろ後始末
//今回は必ずここに入る
}
finally
{
//いろいろ後始末
}
...
}
//デストラクタ
~Klass()
{
//ファイナライザを呼び出す
!Klass()
}
// ファイナライザ
!Klass()
{
//ログ出力の後始末をする
...
}
};
// 以下ネイティブC++クラス
// iniファイルから設定を読み込むクラス
class ReadIniFile
{
public:
void readIniFile()
{
// 指定のiniファイルが開けなかった場合例外を投げる
// 今回は必ずthrowされる
ifstream fs;
fs.open(指定のファイルパス);
if(!fs)
throw MyExeption("コメント");
...
}
};
// ログの設定ファイルを読み込むクラス
class ReadSettingFile
{
public:
void readSettingFile()
{
ReadIniFile readIniFile;
try
{
readIniFile.readIniFile();
}
catch(MyExeption& ex)
{
//コメントを追加して自分自身をthrowします
ex.addInfo("コメント");
}
...
}
};
ご指摘、ご教授いただけるとありがたいです。
|