Подтвердить что ты не робот

Я нашел ошибку в JIT/CLR - теперь как мне отлаживать или воспроизводить ее?

У меня есть дорогостоящее многопоточное приложение на С#, которое, похоже, постоянно срабатывает после 30-90 минут работы. Ошибка, которую она дает, -

Среда выполнения столкнулась с фатальной ошибкой. Адрес ошибки был равен 0xec37ebae, на потоке 0xbcc. Код ошибки: 0xc0000005. Эта ошибка может быть ошибкой в ​​CLR или в небезопасных или не поддающихся проверке частях кода пользователя. Общие источники этой ошибки включают ошибки маршалинга пользователя для COM-interop или PInvoke, которые могут повредить стек.

(0xc0000005 - код ошибки для Нарушение прав доступа)

Мое приложение не вызывает какой-либо собственный код или использует любые небезопасные блоки или даже любые типы, не совместимые с CLS, такие как uint. Фактически, строка кода, которую говорит отладчик, вызвала сбой

overallLength += distanceTravelled;

Если оба значения имеют тип double


Учитывая все это, я считаю, что авария должна быть связана с ошибкой в ​​компиляторе или CLR или JIT. Я хотел бы выяснить, что вызывает его, или, по крайней мере, написать меньшую репродукцию для отправки в Microsoft, но я понятия не имею, с чего начать. Мне никогда не приходилось просматривать CIL-двоичный файл, или скомпилированный JIT-выход, или собственный стек (нет управляемой стека в момент сбоя), поэтому я не знаю, как это сделать. Я даже не могу понять, как просмотреть состояние всех переменных во время сбоя (VS, к сожалению, не скажет мне, что это происходит после управляемых исключений, и вывод их в консоль/файл замедлит работу приложение 1000 раз, что, очевидно, не является вариантом).

Итак, как я могу отладить это?


[Изменить] Скомпилирован под VS 2010 SP1, на котором запущена последняя версия .Net 4.0 Client Profile. По-видимому, это ".Net 4.0C/.Net 4.0E,.Net CLR 1.1.4322"

4b9b3361

Ответ 1

Я хотел бы выяснить, что вызывает его, или, по крайней мере, написать меньшее воспроизведение для отправки в Microsoft, но я понятия не имею, с чего начать.

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

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

Кроме того, проверьте, что вы используете последнюю версию всего. Было бы неприятно тратить дни на отладку (что, вероятно, я боюсь), а затем в итоге получится ответ "Да, мы знаем об этом - это была ошибка в .NET 4, которая была исправлена ​​в .NET 4.5" например. Если вы можете воспроизвести его на различных версиях каркаса, это будет еще лучше:)

Затем вырезать все, что вы можете в программе:

  • Есть ли у него пользовательский интерфейс? Если возможно, удалите это.
  • Использует ли он базу данных? Посмотрите, можете ли вы удалить весь доступ к базе данных: определенно любой вывод, который не используется позже, и в идеале вводит тоже. Если вы можете жестко закодировать ввод в приложении, это было бы идеально, но если нет, файлы будут проще для репродукций, чем доступ к базе данных.
  • Он чувствителен к данным? Опять же, не зная много о приложении, трудно понять, полезно ли это, но если он обрабатывает много данных, можете ли вы использовать бинарный поиск, чтобы найти относительно небольшой объем данных, который вызывает проблему?
  • Должен ли он быть многопоточным? Если вы можете удалить все потоки, очевидно, что, возможно, это займет много времени, чтобы воспроизвести проблему, но все равно это происходит вообще?
  • Попробуйте удалить биты бизнес-логики: если ваше приложение компонентно соответствующим образом, вы, вероятно, можете подделать целые значимые компоненты, сначала создав реализацию заглушки, а затем просто удалив вызовы.

Все это постепенно уменьшит размер приложения, пока оно не станет более управляемым. На каждом шаге вам нужно будет запустить приложение еще раз, пока он не сработает, или вы уверены, что он не потерпит крах. Если у вас есть много машин, доступных вам, это должно помочь...

Ответ 2

tl; dr Убедитесь, что вы компилируете .Net 4.5


Это звучит подозрительно, как та же ошибка, найденная здесь. На странице MSDN:

Эта ошибка может возникать, когда сборщик мусора освобождает и уплотняет память. Ошибка может произойти, если включена Concurrent Garbage Collection, и появляется некоторая комбинация коллекции мусора для переднего плана и фоновой сборки мусора. Когда эта ситуация случится, вы увидите один и тот же стек вызовов снова и снова. В куче вы увидите один свободный объект, и до его окончания вы увидите еще один свободный объект, разрушающий кучу.

Исправление заключается в компиляции в .Net 4.5. Если по какой-то причине вы не можете этого сделать, вы также можете отключить одновременную сборку мусора, отключив gcConcurrent в файле app.config:

<configuration>
   <runtime>
       <gcConcurrent enabled="false"/>
   </runtime>
</configuration>

Или просто скомпилируйте x86.

Ответ 4

Загрузите Отладочный диагностический инструмент v1.2

  • Запустить программу
  • Добавить правило "Сбой"
  • Выберите "Конкретный процесс"
  • на странице "Расширенная настройка" задайте свое исключение, если вы знаете, в каком исключении оно не работает или просто покинуть эту страницу, как
  • Установить расположение userdump

Теперь дождитесь сбоя процесса, файл журнала создается DebugDiag. Теперь активируйте вкладку Advanced Analysis, выберите Crash/Hang Analyzers в верхнем списке и файл дампа в нижнем списке и нажмите "Начать анализ". Это будет генерировать html-отчет для вас. Надеюсь, вы нашли полезную информацию в этом отчете. Если у вас возникли проблемы с анализом, загрузите html-отчет где-нибудь и разместите здесь URL-адрес, чтобы мы могли сосредоточиться на нем.

Ответ 5

Мое приложение не вызывает какой-либо собственный код или использует какие-либо небезопасные блоки или даже любые типы, не совместимые с CLS, такие как uint

Вы можете подумать об этом, но потоки, синхронизация через семафор, мьютекс, он все обрабатывает, все являются родными..net - это слой поверх операционной системы, сам .net не поддерживает чистый код clr ​​для многопоточных приложений, это потому, что OS уже делает это.

Скорее всего, это ошибка синхронизации потоков. Вероятно, несколько потоков пытаются получить доступ к общему ресурсу, например файлу и т.д., Который находится за пределами границы clr.

Вы можете думать, что не имеете доступа к com и т.д., но когда вы вызываете определенный API, например, получаете путь к папке рабочего стола и т.д., он вызывается через shell com API.

У вас есть два варианта:

  • Опубликуйте свой код, чтобы мы могли ознакомиться с узким местом
  • Редизайн вашего приложения с использованием .net-параллельной инфраструктуры потоков, которая включает в себя множество алгоритмов, требующих интенсивных операций ЦП.

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

Ошибка в clr редка, потому что clr очень устойчив. Но плохо написанный код может привести к ошибке, появляющейся как ошибка в clr. Clr не может и никогда не обнаружит, является ли ошибка в вашем коде или в самом clr.

Ответ 6

  • Запустили ли вы тест памяти для своей машины, поскольку один раз у меня были сопоставимые симптомы, один из моих тусклых дефектов оказался ошибочным (в Win7 включен очень хороший файл памяти; http://www.tomstricks.com/how-to-test-your-ram-or-memory-with-windows-memory-diagnostic-tool-in-windows-7/)

  • Это может быть проблема с нагревом/дросселированием, если ваш процессор становится слишком горячим после этого периода времени. Хотя это произойдет раньше imho.

  • Должен быть файл дампа, который вы можете проанализировать. Если вы никогда не делали этого, найдите того, кто это сделал, или отправите его в microsoft

Ответ 7

Я предлагаю вам немедленно открыть запрос поддержки через http://support.microsoft.com, так как ребята поддержки могут показать вам, как собирать необходимую информацию.

Вообще говоря, как и @paulsm4 и @psulek, вы можете использовать WinDbg или Debug Diag для захвата аварийных дампов процесса, и внутри него вся необходимая информация встроена. Однако, если вы впервые используете эти инструменты, вы можете быть озадачены. Группа поддержки Microsoft может предоставить вам пошаговые инструкции по ним, или они могут даже настроить сеанс Live Meeting для вас, чтобы захватить данные, так как программа так сильно падает.

После того, как вы знакомы с инструментами, в будущем вы сможете более легко выполнить аналогичное устранение неполадок,

http://blogs.msdn.com/b/lexli/archive/2009/08/23/when-the-application-program-crashes-on-windows.aspx

Кстати, еще рано говорить "Я нашел ошибку". Хотя вы, очевидно, не можете найти в своей программе зависимость от собственного кода, он может по-прежнему иметь зависимость от собственного кода. Мы не должны делать вывод, прежде чем отлаживать эту проблему.