私はC#の初心者です。最近、アプリケーション(vs2008)を更新すると、次の問題が発生しました。
アプリケーションには、次のような C++ 関数ヘルパーがあります。
array<float>^ Variant::CopyToFloats()
{
unsigned int n = this->data_uint8->Length;
array<float>^ dst = gcnew array<float>(n); //<<OutOfMemoryException happened here
for (unsigned int i = 0; i < n; i++)
dst[i] = (float)this->data_uint8[i];
return dst;
}
c# ファイルでは、
for(int i=0; i<m; i++)
{ for(int j=0; j<n; j++)
{
float[] scan = data[i].CopyToFloats();
for(int k=0; k<nn; k++)
sample[k]=scan[function(i,j)];
}
}
アプリケーションを実行すると、OutOfMemoryException が発生します。
次に、次のコードを追加しました
Process proc = Process.GetCurrentProcess();
long memory = proc.PrivateMemorySize64;
外側のループの前後で、スキャンのメモリが解放されていないことがわかりました。
私は次の方法を試しました:
1.GC.Collect()を使用して/使用せずに、スキャンをクリアしてnullに設定します
for(int i=0; i<m; i++)
{ for(int j=0; j<n; j++)
{
float[] scan = data[i].CopyToFloats();
for(int k=0; k<nn; k++)
sample[k]=scan[function(i,j)];
}
Array.Clear(scan, 0, scan.Length);
scan = null;
//GC.Collect();
}
GC.Collect() を呼び出すと、プログラムの実行が非常に遅くなりました。呼び出さなくても、プログラムは OOME としてクラッシュしました。
どのメモリが解放されていないのだろうか?gcnew によって作成されたスキャンまたはアレイ?
2.配列のサイズが大きい(>500000)ので、ループに入る前に大きなサイズの配列を割り当てます。
float[] scan = new float[data[0].GetSize()];
for(int i=0; i<m; i++)
{ for(int j=0; j<n; j++)
{
scan = data[i].CopyToFloats();
for(int k=0; k<nn; k++)
sample[k]=scan[function(i,j)];
}
}
しかし、OOME はまだ発生しました。ここから、gcnew で作成した配列のメモリが解放されていないことは確かです。私は正しいですか?私が正しければ、なぜリリースされなかったのですか?この記憶を解放する方法はありますか?私が正しくない場合は、アドバイスをお願いします。