Гейзенбаг:Программа WinApi дает сбой на некоторых компьютерах

StackOverflow https://stackoverflow.com/questions/132116

Вопрос

Пожалуйста помоги!Я действительно в замешательстве.Моя программа представляет собой небольшой персональный менеджер заметок (в 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.Я установил для этой опции значение «Не установлено», и ошибка исчезла.Уф!

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

Это было полезно?

Решение

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

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

-ОБЪЯВЛЕНИЕ

Другие советы

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

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

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

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

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

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

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

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

Другой вариант — зарегистрировать собственный обработчик исключений, обрабатывать исключение и писать минидамп где угодно.Подробное описание можно найти на Статья «Посмертная отладка вашего приложения с помощью минидампов и Visual Studio .NET» проекта кода.

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

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

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

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

Загрузите Инструменты отладки для Windows упаковка.Правильно задайте пути к символам, затем запустите приложение под WinDbg.В какой-то момент он сломается из-за нарушения прав доступа.Затем вам следует запустить команду «!analyze -v», которая довольно умна и должна дать вам подсказку о том, что происходит не так.

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

Попробуйте переопределить распределители, чтобы они обнуляли память при выделении.Проблема исчезнет (или станет более воспроизводимой?)

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

Переполнение стека!;)

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

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

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

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

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

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

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

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

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

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

Вы упомянули процессоры AMD.Вы исследовали, существует ли аналогичная версия видеокарты/драйвера и/или конфигурация на машинах, которые вышли из строя?На этих машинах всегда вылетает или время от времени?Возможно, запустите инструмент «Информация о системе» на этих машинах и посмотрите, что у них общего.

Для меня это похоже на повреждение стека.Мой любимый инструмент для их отслеживания — ИДА Про.Конечно, у вас нет такого доступа к машине пользователя.

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

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

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

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

Удачи!

РЕДАКТИРОВАТЬ:

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top