Приложение VB6, вызывающее исключение OutOfMemory .NET DLL

У нас есть приложение VB6, которое обращается к .NET DLL. Иногда, после того как приложение VB6 работало в течение длительного времени и часто вызывало код .NET, сторона .NET выдает исключение OutOfMemory, даже если на машине имеется достаточно памяти. Объем памяти VB6 также далеко не предел.

Сохраняет ли сторона .NET отдельный пул памяти? Или это отдельно от пула памяти приложения VB6?

Если он отдельный, есть ли способ увидеть, насколько он велик? Единственными огромными элементами памяти в моем диспетчере задач являются SQL Server и приложение VB6 (оба ожидаются).

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


person Patrick Burleson    schedule 12.11.2009    source источник


Ответы (4)


Похоже, где-то утечка памяти, и если предположить, что dll и вызывающее приложение верны, это может быть в вызове. Проверьте типы данных параметров и byref против byval. Параметры в .net по умолчанию byval, в vb6 byref. В каждом из них есть различные типы строк, которые не всегда правильно преобразуются при вызове библиотеки.

person xpda    schedule 15.11.2009

Ответ оказался очень простым:

.NET DLL, созданная с конфигурацией DEBUG, будет протекать во время работы.

Переход на сборку RELEASE решил мою проблему.

Задний план:

Наконец-то я получил ANTS для отладки приложения VB6 и просмотра процесса .NET (пришлось изменить код VB6, чтобы как можно скорее загрузить код .NET). Как только я это сделал, я увидел огромное количество объектов со слабыми ссылками, чьим родителем был __ENCList. Эти классы позволяют редактировать и продолжать во время отладки. Быстрый поиск в Google сразу же показал, что это было вызвано использованием сборки DEBUG.

Мой поиск Google

Ссылки:

Слабые ссылки в сборке отладки

person Patrick Burleson    schedule 25.01.2010

Первое, что нужно проверить, это закрепление объектов в памяти. В многопоточной среде это может довольно быстро выйти из-под контроля в зависимости от того, как написан код. Когда .NET собирается захватить больше памяти, она будет занимать ее блоками по 8, 16 или 32 МБ, и эти блоки должны быть полностью чистыми. То есть у вас могут быть сотни МБ свободной памяти, но если нет 32-мегабайтного свободного блока, в котором нет ничего другого, вы получите OOM, который вы видели. Я настоятельно рекомендую приобрести профилировщик памяти, такой как ANTS, и присмотреться к вещам.

person Sonny Boy    schedule 12.11.2009
comment
К сожалению, это однопоточное приложение. Однако я посмотрю на вещи с ANTS. Возможно, у меня серьезная фрагментация памяти. - person Patrick Burleson; 12.11.2009
comment
Bugger, кажется довольно сложным использовать ANTS, когда родительский процесс является исполняемым файлом VB6, который загружает .NET dll. - person Patrick Burleson; 12.11.2009

Чаще всего эту ошибку следует считать из GDI Objects. Проверьте счетчик GDI/Handles на вкладке процессов диспетчера задач или используйте GDIView.

person wqw    schedule 12.11.2009
comment
Я тоже посмотрю на это. Кажется, я помню, что в диспетчере задач было около 100 объектов GDI. Кажется, это намного меньше установленного в реестре лимита в 10 000. - person Patrick Burleson; 12.11.2009