Вызывается System.OutOfMemory. Как найти виновника?
Я использую Visual С# Express 2008, и у меня есть приложение, которое запускается в форме, но использует поток с функцией делегированного отображения, чтобы позаботиться о практически всей обработке. Таким образом, моя форма не блокируется во время обработки задач.
В последнее время, повторив повторный процесс несколько раз (программа обрабатывает входящие данные, поэтому, когда данные поступают, процесс повторяется), мое приложение выйдет из строя с ошибкой System.OutOfMemory.
Трассировка стека в сообщении об ошибке бесполезна, поскольку она направляет меня только в ту строку, где я вызываю функцию делегированной формы.
Я слышал, что люди говорят, что используют ProcMon от SysInternals, чтобы понять, почему такие ошибки случаются. Но я, для жизни, не могу понять. Объем памяти, который я использую, не изменяется по мере запуска программы, если она поднимается, она возвращается. Кроме того, даже если это происходит, как мне понять, какая часть моей программы является проблемой?
Как я могу заняться расследованием этой проблемы?
EDIT:
Итак, после углубления этой проблемы я просмотрел все, что я когда-либо повторил. Было несколько случаев, когда у меня была hugematrix = new uint [gigantic], поэтому я избавился от примерно 3 из них.
Вместо того, чтобы избавиться от ошибки, теперь она намного более скрыта и запутана.
Мое приложение принимает входящие данные и отображает его с помощью OpenGL. Теперь вместо того, чтобы бросать "System.OutOfMemory", он просто ничего не делает с OpenGL.
Единственное отличие моего кода заключается в том, что я не создаю новые матрицы для хранения данных, которые я рисую. Таким образом, я надеюсь, что мой массив останется в одном месте в памяти и не делает ничего самоубийственного для моего LOH.
К сожалению, это искажает зверя далеко за пределами моих скудных средств. С появлением нулевых ошибок, и все мои структуры данных, по-видимому, все еще правильно заполнены, как я могу найти свою проблему? Использует ли OpenGL память в неясном ключе, чтобы не бросать исключения, когда он терпит неудачу? Является ли память еще проблемой? Как узнать? Все профайлы памяти в мире, похоже, мне очень мало говорят.
EDIT:
С лодками поддержки этого сообщества (с дополнительными привилегиями для Amissico) ошибка, наконец, была искоренена. По-видимому, я добавлял элементы в список OpenGL и никогда не снимал их с списка.
Приложение, которое, наконец, привлекло меня, было .Net Memory Profiler. Во время аварии он показал 1,5 ГБ данных в категории <unknown>
. Благодаря процессу устранения (все остальное в списке, который был назван) последней вещью, которая должна быть исключена из списка, была ссылка на OpenGL-рендеринг. Остальное - история.
Ответы
Ответ 1
Основываясь на описании в ваших комментариях, я подозреваю, что вы либо неправильно распоряжаетесь своими изображениями, либо у вас есть серьезная фрагментация больших объектов и, когда вы пытаетесь выделить новое изображение, не имеют достаточного смежного доступное пространство. См. Этот вопрос для получения дополнительной информации - Фрагментация кучи больших объектов
Ответ 2
Вам нужно использовать профилировщик памяти, например, профилировщик памяти муравьев, чтобы узнать, что вызывает эту ошибку.
Вы перерегистрируете обработчик событий в каждом цикле и не отменяете его?
Ответ 3
Профилировщик CLR для .NET Framework 2.0 на http://www.microsoft.com/downloads/details.aspx?familyid=A362781C-3870-43BE-8926-862B40AA0CD0&displaylang=en
Наиболее распространенной причиной фрагментации памяти является чрезмерное создание строк.
Ответ 4
Следующие соображения:
- Убедитесь, что созданные вами потоки уничтожены (прерваны или возвращены функции). Слишком много потоков может привести к сбою приложения, хотя в диспетчере задач память не слишком высока.
- Утечка памяти. Да, да, вы можете привести их в .net довольно хорошо, не указав ссылку на нули. Это можно решить, используя профилиры памяти, такие как dotTrace или ANTI Memory Profiler.
Ответ 5
У меня также была проблема OutOfMemoryException:
Microsoft Visual С# 2008 Сокращение количества загруженных DLL
Причиной была фрагментация виртуального адресного пространства на 2 ГБ ГБ, а плакат nobugz предложил утилиту Sysinternal Vmmap, которая была очень полезна для диагностики. Вы можете использовать его, чтобы проверить, становятся ли ваши свободные области памяти более фрагментированными с течением времени. (Сначала сортируйте по размеру, затем по типу → обновите повторную сортировку, и вы можете увидеть, уменьшаются ли смежные блоки свободной памяти)