Нарушение доступа в коде, который не является моим
Я не уверен, как это сделать. У меня есть программа на С#, состоящая исключительно из управляемого кода, работающего в .NET 4.5. После некоторого времени работы в каком-то случайном времени я получаю сообщение об ошибке "Необработанное исключение типа" System.AccessViolationException "произошло в mscorlib.dll". Поскольку я запускаю его из Visual Studio (2012), я нажимаю "break" и представлен следующий стек вызовов:
mscorlib.dll!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP) + 0x47 bytes
[Native to Managed Transition]
[email protected]() + 0xc bytes
[email protected]() + 0x4f bytes
[email protected]() + 0x2b bytes
[email protected]() + 0xf bytes
[email protected]() + 0x22 bytes
mdnsNSP.dll!7177aa48()
[Frames below may be incorrect and/or missing, no symbols loaded for mdnsNSP.dll]
mdnsNSP.dll!71775b06()
mdnsNSP.dll!71774ded()
mdnsNSP.dll!71774e8c()
bcryptprimitives.dll!746d1159()
bcryptprimitives.dll!746d1137()
[email protected]() + 0x14 bytes
[email protected]() + 0xc bytes
[email protected]() + 0xc bytes
[email protected]() + 0x1a bytes
Интересная вещь, которую я замечаю, заключается в том, что ничто в стеке вызовов не является моим кодом.
Какую стратегию вы бы посоветовали использовать для поиска пути? Или вы видели проблему, подобную этой, и у вас есть советы?
Поскольку исключение, похоже, не включает мой код, я не знаю, какую информацию включить, что было бы полезно при ответе на вопрос, но спросите меня, есть ли что-нибудь еще, что я должен включить.
Поскольку ошибка может быть связана с IO (поскольку PerformIOCompletionCallback находится в верхней части стека), это список типичных задач ввода-вывода, выполняемых этим приложением:
- TcpListener.AcceptTcpClientAsync
- NetworkStream.Write/BeginRead/EndRead
- SqlCommand.BeginExecuteReader/EndExecuteReader
- StreamWriter.WriteLine
Другие примечания:
- Кажется, что это примерно повторяемо - я получаю ту же ошибку в одном и том же месте (PerformIOCompletionCallback), но должен ждать другой промежуток времени, чтобы получить ее (в порядке минут).
- Я не думаю, что могу изготовить небольшую программу, которая надежно освещает проблему. Моя программа обрабатывает многие тысячи аналогичных операций ввода-вывода, прежде чем ударит эту ошибку.
Edit:
На основании предложения @Kevin, что Mdnsnsp.dll от Bonjour, я удалил Bonjour и попробовал еще раз. Исключение сохраняется, но стек вызовов намного чище:
mscorlib.dll!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP) + 0x47 bytes
[Native to Managed Transition]
[email protected]@12() + 0x12 bytes
[email protected]() + 0x27 bytes
[email protected]() + 0x1b bytes
Я предполагаю, что установщик Bonjour установил некорректную DLL-карту для сетевого трафика, но ее удаление не устранило проблему.
Edit:
Я временно перекодировал все мои функции unsafe
, используя более медленные "безопасные" эквиваленты, чтобы исключить это как подозреваемого. Теперь ни одна из сборок приложения не скомпилирована с использованием небезопасного коммутатора. Проблема все еще сохраняется. Повторяю, у меня теперь нет небезопасного кода, нет собственного кода и нет вызовов P/Invoke (в коде пользователя) в этом приложении, но я все еще испытываю AccessViolationException
, как описано выше.
Ответы
Ответ 1
Так как его PerformIOCompletionCallback вызывает ошибку, я бы посмотрел на ваши асинхронные вызовы ввода-вывода.
- TcpListener.AcceptTcpClientAsync
- NetworkStream.Write/BeginRead/EndRead
- SqlCommand.BeginExecuteReader/EndExecuteReader
Ошибка возникает, потому что зарегистрированный дескриптор больше недействителен. Поскольку это происходит в управляемом коде, причина будет заключаться в управляемом объекте и НЕ из сторонней библиотеки DLL.
Ответ 2
Не знаю, может ли это помочь вам, но похоже, что мы столкнулись с аналогичной проблемой несколько лет назад. Насколько я помню, наше исследование указывало на dll в другой программе - мы обнаружили, что нарушения доступа к памяти могут быть вызваны антивирусами (в нашем случае NOD32), брандмауэрами или сетевыми снифферами/контроллерами трафика.
Попробуйте проверить журнал приложений (Панель управления → Система и безопасность → Администрирование → Просмотр событий) для ошибок, вызванных вышеуказанными приложениями. Если проблема с другой программой, попробуйте отключить/удалить ее и снова проверить, если в вашей программе все еще появляется сообщение об ошибке.
UPD Вы пытались воспроизвести эту проблему в чистой тестовой среде?
Ответ 3
Вы можете использовать debugdiag, чтобы узнать, что вызывает AccessViolationException на вашем компьютере. Настройте правило сбоя для процесса и просмотрите файлы дампа и журнала. Надеюсь, вы получите дополнительную информацию по этому вопросу. Также убедитесь, что ваш компьютер запускает последние обновления Windows bcos. У меня была аналогичная проблема, которая была решена в обновлении безопасности для версии CLR.