Подтвердить что ты не робот

Можно ли поймать исключение нарушения доступа в .NET?

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

4b9b3361

Ответ 1

Вы не должны. Нарушение доступа является серьезной проблемой: это непредвиденная попытка записать (или прочитать) неверный адрес памяти. Как пояснил Джон, неуправляемая 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. Более подробная информация приведена выше.

Ответ 2

Да.

В вашем приложении App.confg введите следующий код в тег <configuration>:

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

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

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

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

Ответ 3

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

Ответ 4

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

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

[HandleProcessCorruptedStateExceptions]
public void MyMethod()
{
    try
    {
        NaughtyCall();
    }
    catch (AccessViolationException e)
    {
        // You should really terminate your application here
    }
}

Ответ 5

вы можете обернуть вызов неуправляемой 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 внедрил изменение в поведении, теперь невозможно поймать поврежденное состояние за исключением случаев, когда вы специально "попросите" время выполнения для этого.