Частично сбой приложения? Как я могу поймать неуловимые исключения? - PullRequest
9 голосов
/ 27 июля 2010

У меня есть программа, написанная на C #, работающая на устройстве Windows CE (на Compact Framework).Он обрабатывает минимальные действия пользователя (нажатия кнопок), использует последовательный порт и связь TCP / IP.

Проблема в том, что иногда программное обеспечение отключается само по себе.В фоновом режиме приложение (или части приложения), кажется, все еще работает (по крайней мере, в одном задокументированном случае), потому что оно использует последовательный порт, поэтому перезапуск приложения не помогает.Я не могу воспроизвести проблему, так как это происходит в большинстве случаев, когда нет взаимодействия с пользователем, нет связи через последовательный порт, а сетевая связь - это все сообщения «Я все еще жив», программное обеспечение просто сбоит, казалось бы, без причины.(Я пытаюсь сделать так, чтобы это происходило в режиме отладки, чтобы хотя бы узнать, в чем проблема в коде, если это программная ошибка, но мне пока не повезло.)

Так как у меня заканчиваетсяПо идее, вопрос таков: какая ошибка или исключение или действие ОС или аппаратная неисправность могут вызвать такое поведение?

Проблема наблюдалась на разных устройствах одного типа, поэтому она не должна быть аппаратной ошибкой.(Или все мое оборудование имеет ту же ошибку.) Исключения обрабатываются, поэтому это не должно быть исключением.Необработанные исключения также обрабатываются, поэтому это также не должно быть необработанным исключением.(Я предполагаю, что это вызвано StackoverflowException, потому что я не знаю других исключений, которые не могут быть перехвачены, но в коде нет рекурсии, по крайней мере, не по своей воле, поэтому это не должно бытьвозможность тоже.)

Ответы [ 3 ]

10 голосов
/ 27 июля 2010

Некоторые исключения не могут быть перехвачены и отличаются от версии .NET к версии .NET. И некоторые исключения могут быть перехвачены и зарегистрированы, но не могут быть восстановлены из (исключения памяти). Однако их можно отладить (они называются исключения первого шанса , первый шанс всегда для отладчика, второй шанс для кода, благодаря JeroenH за указание это из) Вот пост в CodeProject, который объясняет этот принцип .

Что вы должны сделать, это выбрать некоторые возможные исключения в Visual Studio, которые, как вы подозреваете, могут возникнуть, и подключить отладчик к работающему экземпляру.

Наличие у вас неуправляемых ресурсов (последовательный порт) означает, что вы можете иметь неуправляемые утечки (не правильно использующие IDisposable + using) и неуправляемые исключения. Эти исключения могут быть перехвачены только с пустым catch (т.е. без указания четного Exception, который является , а не родителем неуправляемых исключений) в блоке try / catch.

PS: некоторое неопределенное поведение может возникнуть, когда исключения вызываются в блоках finally или в финализаторах / деструкторах. Кроме того, немногие исключения распространяются через границы потоков и завершают все потоки.

Редактировать

Чтобы прояснить ситуацию, есть несколько исключений, которые CLR (и его спецификация) определяют как неуловимые. По сути, это все исключения, которые пересекают границы потоков. Эти асинхронные исключения, возникающие в пределах блокировки, приводят к повреждению состояния. Самыми известными являются OutOfMemoryException, ThreadAbortException и StackOverflowException. Когда OutOfMemoryException или StackOverflowException происходит в синхронном коде, маловероятно, что вы можете исправить состояние, и CLR прекратит работу вашего приложения.

Кроме того, есть ExecutionEngineException и BadImageFormatException, которые не должны встречаться в проверяемом коде и не должны быть перехвачены. Исключения, такие как TypeLoadException и MissingMemberException, иногда могут быть перехвачены, а иногда нет (если отсутствует связанная сборка, их будет трудно перехватить, и не следует, но если вы используете отражение, вы должны перехватить это).

Вкратце: исключения должны быть перехвачены в потоке, в котором они происходят. Вы не сможете перехватывать исключения, если они возникают в другом потоке, потому что они не распространяются (за исключением ThreadAbortException). Ваше приложение остается в живых после исключения (по крайней мере, вы думаете), поэтому логично предположить, что исключение не происходит в потоке, в котором вы пытаетесь его перехватить. Используя окно «Отладка> Исключения», вы можете выбрать любое исключение и разбить его на код при возникновении.

Примечание об исключении

Добавлена ​​заметка об управляемых и неуправляемых исключениях. Вы не можете перехватить неуправляемое исключение, используя catch (Exception e), потому что неуправляемое исключение не наследуется от Exception. Вместо этого используйте пустой улов, который перехватит любое неуправляемое исключение для вас. Оберните это вокруг методов вашего приложения и точки входа потока, и вы сможете перехватить большинство перехватываемых исключений.

3 голосов
/ 27 июля 2010

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

Вы p / вызываете или делаете небезопасные вызовы?Если вы вызываете API и вызываете что-то вроде переполнения буфера или повреждения стека, вы увидите такое поведение (хотя часто вы будете получать жалобы в диалоговом окне ОС.

Отслеживание этих данных часто бывает сложным.такое устройство CE - есть ли у него порт отладки (обычно это последовательный порт)? Весьма вероятно, что исключение будет выводить сообщение туда, поэтому, если у вас есть доступ к нему, это хорошая отправная точка. Если у вас есть KITLзапуск ОС в режиме отладки во время работы приложения также может перехватывать все, что происходит.

2 голосов
/ 27 июля 2010

Если вы запускаете вторичные потоки, используя класс Thread, и не указываете, что они являются фоновыми потоками, они будут поддерживать выполнение вашего процесса до тех пор, пока он не завершится, даже если основной поток завершен (т. Е. Основная форма закрыта, а Main метод вернулся.)

Если бы у вас было StackOverflowException, ваш процесс был бы полностью уничтожен Windows, так что это не так.

...