Простой массив C #, выбрасывающий исключение OutOfMemory - PullRequest
5 голосов
/ 13 декабря 2011

У меня довольно большой, довольно простой массив, который отслеживает 750 000 записей.В 64-битном .NET все работает нормально;однако на 32-битном клиенте происходит сбой с исключением OutOfMemory.Я знаю, что у меня не хватает памяти.Клиент, нуждающийся в этой программе, не может использовать 64-битную версию.

Компилируется следующий псевдокод ( edit: , исходный код не компилируется из-за опечатки, это было исправлено) и выдает то же исключение при нацеливании на архитектуру x86 на двух машинах:

  • Windows XP, 32-разрядная машина, работающая на 4 ГБ ОЗУ и .NET Framework4
  • Windows 7, 64-разрядная машина с 8 ГБ ОЗУ и .NET Framework 4

Редактировать: Переключение флага компилятора на явно для целевой архитектуры x64 позволяет запускать ее на 64-разрядной машине Windows 7.

using System;

public class Storage
{
    Storage futureStorage;
    int count;
    int years;
    bool isTest;
    bool isSet;
}

public static class Program
{
    public static void Main()
    {
        Storage[] storageArray = new Storage[750000];
        for (int i = 0; i < 750000; i++)
        {
            storageArray[i] = new Storage();
        }
    }
}


Редактировать:

Сеть, в которой работает этот код, является закрытой сетью, без подключения к внешней сети, поэтому публикация более точного кода и соответствующих сведений об исключениях - это чуть больше процесс, над которым я работаю.У меня действительно работает intellitrace, с полными символами отладки и несколькими переключателями компилятора, более подробные сведения, которые необходимо соблюдать, как только я перенесу его в сеть, подключенную к Интернету.


На обеих машинах код взрываетсяоколо 693 000 (693 002 в XP, точнее 693 646 в Windows 7).

У кого-нибудь есть какие-либо идеи относительно возможной проблемы?Когда я делаю дамп и профилирую после кода, я едва использую 25 МБ ОЗУ.

Я бы переключился на небезопасный / неуправляемый, если он мне что-то покупает, но единственная попытка, которую я сделал виз-за этого я не могу использовать свой класс хранилища.

Обновление:

Кажется, что некоторые люди не могут повторить проблему (включая меня на другом компьютере / в сети).

Тем не менее, я придумала решение (использующее LINQ), которое облегчает проблему, теперь оно выдает исключение только 1/5 раза или около того, каждый знает, есть ли какие-либо проблемы или предостережения, которые я должен знать об использовании этого решения, и почему внутреннеон может работать по сравнению с другим?

using System;
using System.Linq;    

public class Storage
{
    Storage futureStorage;
    int count;
    int years;
    bool isTest;
    bool isSet;
}

public static class Program
{
    public IEnumerable<Storage> storageEnumerable;
    public static void Main()
    {
        storageEnumerable = (from x in  Enumerable.Range(0, 750000) select new Storage() {count = x});
        foreach (Storage s in storageEnumerable)
            Console.WriteLine(x);
    }
}

Приведенный выше код LINQ использует гораздо меньше памяти, но исключение все равно возникает;и только на машинах в этой сети, а не на других машинах вне сети (или в этом отношении в пуле приложений IIS).

Учитывая, что другие пользователи с тех пор сообщили, что не могут воспроизвести ошибку, возможно, это зависит от среды или оборудования.Может ли быть средство мониторинга сети или запуск антивирусной программы на этих двух реализациях кода?Если да, то есть ли лучший / рекомендуемый способ инициализации массива, чтобы я этого избежал?

Ответы [ 4 ]

1 голос
/ 22 августа 2012

Может быть, это поможет?

Каков максимальный размер, который может содержать массив?

Ответ говорит, что, возможно, использование List может использовать меньше памяти.

1 голос
/ 13 августа 2012

Для записи, от Джеффри Рихтера (глава темы работы):

32-разрядный процесс имеет не более 2 ГБ доступного адресного пространства. После загрузки нескольких библиотек DLL Win32, загрузки библиотек CLR, выделения собственной и управляемой кучи остается около 1,5 ГБ адресного пространства.

Попытка создать больше потоков приведет к созданию исключения OutOfMemoryException.

Конечно, 64-битный процесс предлагает 8 терабайт адресного пространства, так что теоретически вы можете создать сотни тысяч потоков

Таким образом, после инициализации массива у вас появляется все меньше и меньше свободного места. И в определенный момент у вас нет пустой памяти, и вы получили свой OutOfMemoryException.

Я думаю, что использование LINQ более разумно использует ресурсы, и в некоторых случаях это работает без ошибок.

К сожалению, вы не можете сделать много вещей с этим, извините за это. Единственное, что вы можете сделать

  • используйте не так много объектов в вашем массиве
  • чаще используйте GC.Collect для сбора предметов, которые больше не используются
1 голос
/ 21 августа 2012

Попробуйте сделать хранилище struct вместо class Массив типов vlaue занимает меньше памяти, чем Массив ссылочных типов

1 голос
/ 14 декабря 2011

Я предполагаю, что без дополнительной отладочной информации ваша программа использует виртуальную память.Используйте TaskManager, чтобы исследовать всю используемую память, вы должны добавить эти поля в ваш процесс explorer.Если это то, что вам действительно не хватает памяти.

...