Heisenbug: программа WinApi падает на некоторых компьютерах - PullRequest
8 голосов
/ 25 сентября 2008

Пожалуйста, помогите! Я действительно в своем уме. Моя программа - небольшой менеджер личных заметок (Google для "cintanotes"). На некоторых компьютерах (и, конечно, у меня нет ни одного из них) происходит сбой с необработанным исключением сразу после запуска. Ничего особенного в этих компьютерах сказать нельзя, за исключением того, что они, как правило, имеют процессоры AMD.

Среда: Windows XP, Visual C ++ 2005/2008, необработанный WinApi.

Вот что является определенным в этом «Гейзенбаге»:

1) Сбой происходит только в версии Release.

2) Сбой исчезает, как только я удаляю все, что связано с GDI.

3) BoundChecker не имеет жалоб.

4) Запись журнала показывает, что сбой происходит при объявлении локальной переменной int! Как это может быть? Повреждение памяти?

Любые идеи будут с благодарностью!

ОБНОВЛЕНИЕ: мне удалось отладить приложение на "неисправном" ПК. Результаты:

"Необработанное исключение в 0x0044a26a в CintaNotes.exe: 0xC000001D: недопустимая инструкция."

и разрывы кода на

0044A26A cvtsi2sd xmm1, dword ptr [esp + 14h]

Так что, похоже, проблема была в параметре компилятора «Генерация кода / Включить расширенный набор инструкций». Он был установлен на «/ arch: SSE2» и падал на компьютерах, которые не поддерживают SSE2. Я установил эту опцию на «Не установлено», и ошибка исчезла. Уф!

Большое спасибо всем за помощь !!

Ответы [ 11 ]

10 голосов
/ 25 сентября 2008

4) Запись в журнале показывает, что сбой происходит при объявлении локальной переменной int! как это могло быть? Повреждение памяти?

Каков основной код в исполняемом файле / сборке? Объявление int вообще не является кодом и не может завершиться сбоем. Вы как-то инициализируете int?

Чтобы увидеть код, где произошел сбой, вы должны выполнить так называемый посмертный анализ.

Отчеты об ошибках Windows

Если вы хотите проанализировать сбой, вы должны получить дамп сбоя. Одним из вариантов для этого является регистрация для отчетов об ошибках Windows - требуется немного денег (вам нужен цифровой идентификатор подписи кода) и некоторое заполнение формы. Для получения дополнительной информации https://winqual.microsoft.com/.

Получите аварийный дамп, предназначенный для WER, непосредственно от клиента

Другой вариант - связаться с каким-либо пользователем, который испытывает сбой, и получить от него дамп, предназначенный для WER, напрямую. Пользователь может сделать это, щелкнув Технические детали перед отправкой сбоя в Microsoft - там можно проверить местоположение файла дампа сбоя.

Ваш собственный минидамп

Другой вариант - зарегистрировать свой собственный обработчик исключений, обработать исключение и написать мини-дамп где угодно. Подробное описание можно найти по адресу Пост-Mortem Project Отладка вашего приложения с помощью Minidumps и Visual Studio .NET статья .

5 голосов
/ 25 сентября 2008

Таким образом, он не падает, когда конфигурация является DEBUG Configuration? Есть много вещей, отличных от конфигурации RELEASE: 1.) Инициализация глобалов 2.) Фактический машинный код, сгенерированный и т. Д.

Итак, первый шаг - узнать, какие точные настройки для каждого параметра в режиме RELEASE по сравнению с режимом DEBUG.

-AD

4 голосов
/ 25 сентября 2008

1) Сбой происходит только в версии Release.

Как правило, это признак того, что вы полагаетесь на какое-то поведение, которое не гарантировано, но оказывается верным в отладочной сборке. Например, если вы забыли инициализировать переменные или получили доступ к массиву за пределами. Убедитесь, что вы включили все проверки компилятора (/ RTCsuc). Также проверьте такие вещи, как полагаться на порядок оценки параметров функции (что не гарантируется).

2) Авария исчезает, как только я удаляю все, что связано с GDI.

Может быть, это намек на то, что вы делаете что-то не так с GDI? Используете ли вы РУЧКИ после того, как они были освобождены, например?

2 голосов
/ 25 сентября 2008

Загрузите пакет Средства отладки для Windows . Установите правильные пути символов, затем запустите ваше приложение под WinDbg. В какой-то момент он порвет с нарушением прав доступа. Затем вы должны запустить команду "! Analysis -v", которая довольно умна и должна подсказать вам, что происходит не так.

1 голос
/ 26 сентября 2008

Когда я получаю такие вещи, я пытаюсь запустить код через gimpels PC-Lint (статический анализ кода), поскольку он проверяет различные классы ошибок в BoundsChecker. Если вы используете Boundschecker, включите параметры отравления памяти.

Вы упомянули процессоры AMD. Вы исследовали, существует ли аналогичная версия видеокарты / драйвера и / или конфигурация на машинах, которые дают сбой? Всегда ли это происходит сбой на этих машинах или просто случайно? Может быть, запустите инструмент System Information на этих машинах и посмотрите, что у них общего,

1 голос
/ 25 сентября 2008

"4) Запись журнала показывает, что сбой происходит при объявлении локальной переменной int! Как это может быть? Повреждение памяти?"

Это может быть признаком того, что оборудование на самом деле неисправно или слишком сильно загружено. Узнайте, разогнали ли они свой компьютер.

1 голос
/ 25 сентября 2008

Что говорит авария? Нарушение доступа ? Исключение? Это было бы еще одним ключом к решению этой проблемы с

Убедитесь, что у вас нет предыдущих повреждений памяти при использовании PageHeap.exe

Убедитесь, что у вас нет переполнения стека (массив CBig [1000000])

Убедитесь, что у вас нет неинициализированной памяти.

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

1 голос
/ 25 сентября 2008

Попробуйте Rational (IBM) PurifyPlus. Он ловит много ошибок, которых нет в BoundsChecker.

1 голос
/ 25 сентября 2008

4) Запись журнала показывает, что происходит сбой при объявлении локальной переменной int! Как это могло быть? Повреждение памяти

Я обнаружил, что причиной многочисленных "странных аварий" является разыменование сломанного this внутри функции-члена указанного объекта.

1 голос
/ 25 сентября 2008

Похоже, повреждение стека для меня. Мой любимый инструмент для их отслеживания - IDA Pro . Конечно, у вас нет такого доступа к компьютеру пользователя.

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

Это также может быть связано с повреждением пути исключения, даже если исключение было обработано. Отлаживаете ли вы с включенным «ловить исключения первого шанса»? Вы должны так долго, как можете. Во многих случаях это действительно раздражает через некоторое время.

Можете ли вы отправить этим пользователям проверенную версию вашего приложения? Проверьте Minidump Обработайте это исключение и выведите дамп. Затем используйте WinDbg для отладки на вашем конце.

Другой метод - это запись очень подробных журналов. Создайте опцию «Записывать каждое отдельное действие», попросите пользователя включить ее и отправить вам тоже. Сбросить память в журналы. Проверьте '_CrtDbgReport ()' на MSDN.

Удачи!

EDIT:

Ответ на ваш комментарий: Ошибка при объявлении локальной переменной меня не удивляет. Я видел это много. Обычно это происходит из-за поврежденного стека.

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

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

Многие разработчики используют WinDbg для такого анализа. Вот почему я также предложил Minidump.

...