Найти причину исключения System.AccessViolationException

Наше приложение испытывает странное фатальное исключение System.AccessViolationException. Мы видим это, поскольку настроили событие AppDomain.CurrentDomain.UnhandledException для регистрации исключения.

Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(Form mainForm)
   at Bootstrap.Run() in e:\build-dir\src\Bootstrap.cs:line 25

Само исключение, по-видимому, не содержит больше информации, чем сообщение "Попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая память повреждена".

  • Какие шаги мы можем предпринять сейчас, чтобы найти причину проблемы?
  • Есть ли способ определить недопустимый адрес или значение указателя, вызвавшее сбой?
  • Можем ли мы узнать, какой нативный код библиотеки вызывал проблему?
  • Есть ли больше отладки / трассировки, которые мы можем включить?

ОБНОВИТЬ

  • Может ли это быть вызвано более ранним не-безопасным использованием WinForms API?

4 ответа

То, что вы испытываете, является точным эквивалентом "Программа столкнулась с проблемой и теперь закрывается", за исключением того, что она перехватывается средой выполнения.NET, а не ОС.

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

Единственный способ отследить что-то подобное - запустить собственные библиотеки под отладчиком, который должен перехватить нарушение прав доступа, прежде чем оно попадет на уровень CLR. Это может быть легко или сложно.

Если нативный код является вашим собственным проектом, то самый простой способ настроить это - поместить проект.NET и проект C++ в одно и то же решение и убедиться, что проект.NET ссылается на проект C++. Если вы опубликуете более подробную информацию о вашей среде, я могу дать более конкретные советы.

Трассировка стека указывает на неверные данные в параметре MSG собственного мессенджера диспетчеризации. Вы пытались загрузить символы из Microsoft и проверить параметры этой трассировки стека.

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

У меня была похожая проблема, и в отличие от @BartRead, постоянно. Для меня некоторый код CLI работал нормально в простом приложении для форм Windows, но когда я поместил его в экосистему плагинов larager (многопоточную), сообщения должны были быть обработаны с помощью Application.Run или Application.DoEvents. Если у вас есть доступ к перекачиваемому коду, лучше всего (что мне помогло) было закомментировать все больше и больше фрагментов кода, сохраняя при этом функциональность. Оказалось, что у меня не было GC::Alloc'd обратный вызов / делегат, и, хотя он был закреплен и все еще на него ссылались, он перемещался в памяти или был помечен для сбора.

если вы используете GC Alloc, обязательно уберите за собой!

У меня была эта проблема при выполнении хранимой процедуры с использованием ADO. эта ошибка имела две причины:

  1. плохая строка подключения.
  2. несоответствие типов параметров (передача long для db-int32 или long в nvarchar(10), который короче)

Stacktrace ничего вам не сообщает:-(. Можете ли вы обновить свои пакеты, чтобы увидеть, исчезло ли исключение? Я видел System.AccessViolationException с None-Threadsafe Com-Objects при доступе к свойствам из рабочего потока. Так что да, я могу представить исключение вызвано использованием более ранней небезопасной версии из некоторого API.

Я справился с ситуацией, добавив атрибуты

[HandleProcessCorruptedStateExceptions]
[SecurityCritical]

к методу, в котором я получаю доступ к этим конфликтующим свойствам из COM-объекта. Также мне пришлось добавить

<legacyCorruptedStateExceptionsPolicy enabled="true" />

Я установил свой app.config и смог поймать эти исключения и обработать их с умом.

Дополнительная информация Исключения поврежденного состояния Документы MS Обработка исключений поврежденного состояния и не завершение процесса означает, что вы оставляете путь, где "CLR предлагает довольно надежные гарантии правильности программы и безопасности памяти".

Кредиты на /questions/26600831/kak-obraschatsya-s-accessviolationexception/26600850#26600850

Другие вопросы по тегам