Какие существуют методы для устранения неполадок, связанных с нарушением прав доступа на устройстве Windows Mobile? - PullRequest
3 голосов
/ 31 декабря 2008

У меня есть большое приложение Compact Frameworks V2.0, которое в большинстве случаев работает очень хорошо. На некоторых устройствах примерно раз в день пользователь получает собственную ошибку 0xC0000005, которая не перехватывается стандартным управляемым блоком Try / Catch.

Мое приложение синхронизируется с сервером через вызовы ASMX через фиксированные интервалы. Проблема возникает во время синхронизации. В дополнение к вызову ASMX, который происходит во время синхронизации, существует значительная бизнес-логика, но 98% этого объема - управляемый код. Я просмотрел все свои P / Invokes и нативные библиотеки C ++ приложений, и на данный момент я на 95% уверен, что проблема не в этом.

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

Буду признателен за любые мысли по дальнейшему устранению неполадок.

Ответы [ 2 ]

5 голосов
/ 31 декабря 2008

0xC0000005 - это нарушение прав доступа, поэтому что-то пытается прочитать или записать адрес, к которому у него нет прав доступа. Их, как правило, очень сложно найти, и опыт - один из лучших инструментов (хорошо, что отладчик Platform Builder тоже очень полезен, но это отдельная возможность отладки, требующая опыта, которого у вас, вероятно, нет, или вы уже имели попробовал это). Я считаю, что ведение журналов имеет тенденцию быть менее полезным, чем вычитающее кодирование - удаление вызовов P / invoke с помощью фиктивных управляемых вызовов, когда это возможно.

Нарушения доступа в управляемых приложениях обычно происходят по одной из следующих причин:

  • Вы вызываете / вызываете собственный API, передавая дескриптор управляемому объекту, и собственный API использует этот дескриптор. Если вы получите коллекцию и сжатие во время работы нативного API, управляемый объект может переместиться, и указатель станет недействительным.
  • Вы P / Invoke что-то с буфером, который слишком мал или меньше, чем размер, который вы передаете, и API переполняет чтение или запись
  • Указатель (IntPtr и т. Д.), Который вы передаете в вызов P / Invoke, недействителен (-1 или 0), и нативный не проверяет его перед использованием
  • Вы выполняете P / Invoke собственный вызов, и исходный код исчерпывает память (обычно виртуальную) и не проверяет ошибочные распределения и читает / записывает на неверный адрес
  • Вы используете GCHandle, который не инициализирован или который каким-то образом указывает на уже завершенный и собранный объект (поэтому он не указывает на объект, он указывает на адрес, где раньше был объект)
  • Ваше приложение использует дескриптор чего-то, что стало недействительным в результате сна / пробуждения. Это более эзотерично, но, безусловно, бывает. Например, если вы запускаете приложение с карты памяти, все приложение не загружается в оперативную память. Части в использовании выровнены по требованию для выполнения. Это все хорошо. Теперь, если вы выключите устройство, все драйверы выключатся. При включении питания многие устройства просто перемонтируют устройства хранения. Когда вашему приложению нужно запросить страницу в большем количестве программ, оно больше не там, где оно было, и оно умирает. Подобное поведение может происходить с базами данных в подключенных хранилищах. Если у вас есть открытый дескриптор базы данных, после цикла сна / пробуждения дескриптор соединения может перестать действовать.

Вы заметите здесь тенденцию, что почти все они являются P / Invokes, и это не случайно. Довольно сложно заставить управляемый код сделать это самостоятельно.

1 голос
/ 31 декабря 2008

Моя собственная обработка исключений C ++ не включала асинхронное исключение и, следовательно, не отслеживала исключения нарушения доступа.

Это может / не может быть полезно для моей проблемы, но может быть полезно для других.

Использование параметра / EHa, как описано в этой ссылке, позволит перехватывать исключения следующих типов:

http://msdn.microsoft.com/en-us/library/1deeycx5.aspx

...