Каковы некоторые методы устранения очень периодических нарушений прав доступа на устройстве Windows Mobile?

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

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

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

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


person Kevin    schedule 31.12.2008    source источник
comment
Сможете ли вы убедить, что сбой произошел внутри эмулятора устройства? Встроенная отладка через эмулятор может кое-что вам дать; кроме этого, все, что у вас есть, - это отключить большие части приложения и посмотреть, перестанет ли оно умирать. Другими словами, это совсем не весело.   -  person bobince    schedule 31.12.2008
comment
Tnx ... не совсем ... Я никак не могу убедить его дать сбой ... Я думаю, что это может иметь какое-то отношение к выходу из спящего режима даже после установки требований к питанию. Ни разу не видел проблемы при зарядке устройства.   -  person Kevin    schedule 31.12.2008
comment
Да, сон / бодрствование - это совсем другое дело. Я изменил свой ответ, включив это.   -  person ctacke    schedule 31.12.2008


Ответы (2)


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

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

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

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

person ctacke    schedule 31.12.2008
comment
Спасибо за подробный отзыв. После тщательного обзора кода единственное, что я вижу, попадает в одну из перечисленных выше категорий - это StringBuilder, который я не закрепляю перед отправкой в ​​P / Invoke. Я где-то читал, что сортировка как-то справляется с этим, вы знаете, правильно ли это? - person Kevin; 31.12.2008
comment
Я просто собираюсь попробовать метод вычитания кода, но с минимальным интервалом в один день между сбоями это может быть сложно. Похоже, это происходит только на определенных устройствах, когда они находятся в спящем режиме / не заряжаются, когда они просыпаются для синхронизации. Может ли это быть что-то в собственном коде BSP или компактных фреймворков? - person Kevin; 31.12.2008
comment
В Windows CE вы не можете никогда предполагать, что платформа не виновата. Это определенно может быть проблемой. Что касается StringBuilder, это зависит от использования. Если это синхронный вызов, вы в безопасности. Если это асинхронно, то нет. - person ctacke; 31.12.2008
comment
Еще раз спасибо за дополнительную информацию, это синхронный вызов, поэтому я думаю, что я в безопасности. Подробности в отчете о сбое имеют три значения: ExceptionCode, который равен 0xC00 ExceptionAddr: 0x12341234 и Reading: 0x0000000 Я предполагаю, что 0x00 для чтения, вероятно, будет неудачным распределением памяти. - person Kevin; 31.12.2008
comment
А 0x [OTHERADDR] для чтения означает, что управляемый объект, вероятно, был перемещен или что-то было повреждено. Правильный? В конце концов, имеет ли значение значение ExceptionAddress по отношению к образу DLL? Еще раз спасибо за вашу помощь, это меня озадачило. - person Kevin; 31.12.2008
comment
После просмотра некоторых отчетов, похоже, есть пара значений чтения 0xffffff9c и 0xfffffe6c, они не кажутся действительными адресами, не так ли? - person Kevin; 31.12.2008
comment
Нет, это определенно недействительные адреса. Адрес исключения 0x12341234 также выглядит как повреждение кучи. - person ctacke; 31.12.2008

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

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

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

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

person Kevin    schedule 31.12.2008