まず第一に、メモリが解放されることを保証するものではありません(管理されていないリソースがないため、何も解放しないDispose()
場合は、GCコレクションのオブジェクトをマークしません)。によって使用されるメモリを解放する唯一の信頼できる方法は、それへのすべての参照を失い、ガベージコレクションが発生するのを待つことです(ガベージコレクタがすでに試行されていますが、十分なメモリを解放できませんでした)。また、このような大きなオブジェクト(85000バイトを超えるもの)を割り当てると、いくつかの結果が生じます。これらのオブジェクトは、断片化される可能性がある(圧縮できない)大きなオブジェクトヒープ(LOH)になります。.NETオブジェクトは連続したバイトシーケンスを占有する必要があるため、十分なメモリがある状況につながる可能性がありますが、大きなオブジェクトを格納する余地はありません。この場合、ガベージコレクターは役に立ちません。MemoryStream
MemoryStream
MemoryStream
OutOfMemoryException
ここでの主な問題は、stream
オブジェクトへの参照がスタックに保持され、オブジェクトのガベージコレクションが妨げstream
られていることです(ガベージコレクションを強制しても、GCはオブジェクトがまだ生きていると見なすため、これをチェックしてオブジェクトを作成できますWeakRefrence
) )。このサンプルをリファクタリングすると、修正できます。
static void Main(string[] args)
{
const int bufferSize = 1024 * 1024 * 2;
var buffer = new byte[bufferSize];
for(int i = 0; i < 10; i++)
{
const int writesCount = 400;
Write(buffer, writesCount, bufferSize);
}
}
static void Write(byte[] buffer, int writesCount, int bufferSize)
{
using(var stream = new MemoryStream(writesCount * bufferSize))
{
for(int j = 0; j < writesCount; j++)
{
stream.Write(buffer, 0, buffer.Length);
}
}
}
オブジェクトをガベージコレクションできないことを証明するサンプルを次に示します。
static void Main(string[] args)
{
const int bufferSize = 1024 * 1024 * 2;
var buffer = new byte[bufferSize];
WeakReference wref = null;
for(int i = 0; i < 10; i++)
{
if(wref != null)
{
// force garbage collection
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
// check if object is still alive
Console.WriteLine(wref.IsAlive); // true
}
const int writesCount = 400;
using(var stream = new MemoryStream(writesCount * bufferSize))
{
for(int j = 0; j < writesCount; j++)
{
stream.Write(buffer, 0, buffer.Length);
}
// weak reference won't prevent garbage collection
wref = new WeakReference(stream);
}
}
}