Ответ 1
Изменение от 12 до 24 в примере byte[]
может быть объяснено изменением архитектуры ЦП от 32 до 64 бит. В программах, скомпилированных для x64 или AnyCPU, размер заголовка объекта .NET увеличивается от 12 до 24 байтов.
Для примера double[]
просто используйте калькулятор: 85000 байт /64 бит для двойного типа = 10625 элементов, который уже близок. Учитывая заголовок объекта .NET, результатом является (85000-24)/8 = 10622. Таким образом, нет специальной обработки double[]
.
Кстати, я до сих пор не обнаружил какой-либо рабочей демонстрации для фрагментации LOH, поэтому сам написал. Просто скомпилируйте следующий код для x86 и запустите его. Он даже содержит некоторые подсказки для отладки.
Он не будет работать, если компилироваться как x64, поскольку Windows может увеличить размер файла подкачки, поэтому последующее распределение памяти на 20 МБ может быть успешным снова.
class Program
{
static IList<byte[]> small = new List<byte[]>();
static IList<byte[]> big = new List<byte[]>();
static void Main()
{
int totalMB = 0;
try
{
Console.WriteLine("Allocating memory...");
while (true)
{
big.Add(new byte[10*1024*1024]);
small.Add(new byte[85000-3*IntPtr.Size]);
totalMB += 10;
Console.WriteLine("{0} MB allocated", totalMB);
}
}
catch (OutOfMemoryException)
{
Console.WriteLine("Memory is full now. Attach and debug if you like. Press Enter when done.");
Console.WriteLine("For WinDbg, try `!address -summary` and `!dumpheap -stat`.");
Console.ReadLine();
big.Clear();
GC.Collect();
Console.WriteLine("Lots of memory has been freed. Check again with the same commands.");
Console.ReadLine();
try
{
big.Add(new byte[20*1024*1024]);
}
catch(OutOfMemoryException)
{
Console.WriteLine("It was not possible to allocate 20 MB although {0} MB are free.", totalMB);
Console.ReadLine();
}
}
}
}