Можно ли поймать исключение нарушения доступа в .NET? - PullRequest
29 голосов
/ 22 июля 2010

Что я могу сделать, чтобы поймать AccessViolationException? Это выбрасывается неуправляемой DLL, которую я не контролирую.

Ответы [ 5 ]

29 голосов
/ 22 июля 2010

Ты не должен.Нарушение доступа является серьезной проблемой: это неожиданная попытка записи (или чтения) неверного адреса памяти.Как уже пояснил Джон, неуправляемая DLL могла уже повредить память процесса до того, как было поднято нарушение прав доступа.Это может привести к непредсказуемым последствиям в любой части текущего процесса.

Самое безопасное, что нужно сделать - это сообщить пользователю и сразу же выйти.

Еще некоторые подробности: нарушение прав доступа являетсяИсключение ОС (так называемое SEH или структурированное исключение исключение).Это другой тип исключения, чем управляемые исключения CLR из System.Exception.Вы будете редко видеть исключения SEH в чисто управляемом коде, но если это произойдет, например, в неуправляемом коде, CLR доставит его в управляемый код, где вы также сможете его перехватить 1 .

Однако ловить исключения SEH в большинстве случаев не очень хорошая идея.Дальнейшие подробности разъясняются в статье Обработка исключений из поврежденного состояния в журнале MSDN, где взят следующий текст:

CLR всегда доставлял исключения SEH в управляемый код, используя те же механизмы, что и исключения, создаваемые самой программой.Это не проблема, пока код не пытается обработать исключительные условия, которые он не может разумно обработать.Большинство программ не могут безопасно продолжить выполнение после нарушения прав доступа.К сожалению, модель обработки исключений в CLR всегда поощряла пользователей обнаруживать эти серьезные ошибки, позволяя программам перехватывать любые исключения в верхней части иерархии System.Exception.Но это редко правильная вещь.

1 Это было верно до .NET 3.5.В .NET 4 поведение было изменено.Если вы все еще хотите иметь возможность перехватывать подобные исключения, вам нужно добавить legacyCorruptedState­­ExceptionsPolicy=true в app.config.Дальнейшие подробности см. Выше.

8 голосов
/ 15 сентября 2016

Да.

В вашем App.confg добавьте следующий код в тег * <configuration>:

<runtime>
    <legacyCorruptedStateExceptionsPolicy enabled="true"/>
</runtime>

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

Примечание. Если у вас уже есть тег времени выполнения, просто добавьте к нему <legacyCorruptedStateExceptionsPolicy enabled="true"/>

Вышесказанное работает для .Net 4.5

6 голосов
/ 06 октября 2017

Как отмечали другие, вы не должны "обрабатывать" это условие, но во время разработки удобно отлавливать его для устранения неполадок.

Вы можете пометить управляемый метод с помощью System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsатрибут:

[HandleProcessCorruptedStateExceptions]
public void MyMethod()
{
    try
    {
        NaughtyCall();
    }
    catch (AccessViolationException e)
    {
        // You should really terminate your application here
    }
}
1 голос
/ 22 марта 2013

Прежде всего, я полностью согласен с 0xA3.Но если нет выхода, вы можете обернуть грязную неуправляемую dll в свой собственный процесс и передавать данные через IPC (TCP / IP, namedpipes и т. Д.).Перехватите все исключения и сообщите хост-процессу.Таким образом, ваш хост-процесс в основном защищен от повреждения памяти.

0 голосов
/ 22 июля 2010

вы можете заключить вызов в неуправляемую DLL с помощью блока try-catch. AccessViolationExceptions может быть перехвачен в обычном режиме.Выполнение следующего кода показывает оба сообщения:

try
{
    throw new AccessViolationException();
}
catch (Exception e)
{
    MessageBox.Show(e.Message + e.StackTrace, e.Message, MessageBoxButtons.OK, MessageBoxIcons.Error);
}
MessageBox.Show("Still running..");

Редактировать: .NET 4 представил изменение в поведении , больше нет возможности отловить исключения поврежденного состоянияесли вы специально не "попросите" среду выполнения, чтобы сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...