C# Winforms: отладка стратегий, чтобы найти причину для System.AccessViolationException

В моем приложении winforms я получаю следующее исключение в случайных случаях:

Application: My.Shell.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
Stack:
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG ByRef)
   at System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr, Int32, Int32)
   at System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
   at System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)
   at System.Windows.Forms.Application.Run(System.Windows.Forms.Form)
   at Microsoft.Practices.CompositeUI.WinForms.FormShellApplication`2[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].Start()
   at Microsoft.Practices.CompositeUI.CabApplication`1[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].Run()
   at My.Shell.ModuleLoader.Main() 

Трассировка стека была из окна просмотра событий Windows. (Необработанный обработчик исключений не получил его.)

Я прочитал много статей по этому поводу на SO:

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

3 ответа

Я обнаружил, что UnhandledException а также ThreadException события часто не запускаются в WinForms. В моем приложении у меня есть три разных способа отловить необработанное исключение. Часто это просто try catch который получает это.

static void Main(string[] args)
{
    Application.ThreadException += Application_ThreadException;
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

    try
    {
        var mform = new MainForm();
        Application.Run(mform);
    }
    catch (Exception ex)
    {
        HandleException(ex);
    }
}

private void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
    HandleException(e.Exception);
}

private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    HandleException(e.ExceptionObject as Exception);
}

private void HandleException(Exception ex)
{
    // Do something with it
}

Вероятно, это поможет использовать SOS, разбить первое необработанное исключение и перейти оттуда.

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

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

Я закончил с этим замечательным инструментом: "Debug Diagnostic Tool" от Microsoft. Смотрите подробности на CodeProject

"Средство диагностики отладки (DebugDiag) предназначено для помощи в устранении проблем, таких как зависания, низкая производительность, утечки памяти или фрагментация, а также сбои в любом процессе пользовательского режима". (microsoft.com) Инструмент DebugDiag гораздо проще в использовании по сравнению с другими инструментами для отладки.

Инструмент автоматически отслеживает конкретный процесс и сохраняет файлы дампа в выбираемую папку. Очень удобно;-)

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