Heisenbug: программа WinApi вылетает на некоторых компьютерах

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

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

Похоже, что золотое сечение было ближе всего к ответу.

Constantin 08.10.2008 00:13
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
9
1
2 180
11
Перейти к ответу Данный вопрос помечен как решенный

Ответы 11

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

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

Writig a log shows that the crash happens on a declaration of a local int variable! How could that be? Memory corruption?

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

Спасибо за идею, обязательно вернусь в этом направлении

Alex Jenter 26.09.2008 11:52
Ответ принят как подходящий

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

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

-ОБЪЯВЛЕНИЕ

1) The crash happens only in the Release version.

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

2) The crash goes away as soon as I remove all GDI-related stuff.

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

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

Alex Jenter 26.09.2008 11:56

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

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

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

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

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

Удачи!

Обновлено:

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

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

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

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

Спасибо за все идеи. Я уже написал журнал, и он указывал на объявление переменной типа int. Я не шучу, код был такой: log << "before"; log.flush (); int i; журнал << "после"; log.flush (); - и только «до» было в лог-файле.

Alex Jenter 26.09.2008 11:59

4) Writig a log shows that the crash happen on a declaration of a local int variable! how could that be? Memory corruption?

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

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

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

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

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

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

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

Другой вариант - зарегистрировать собственный обработчик исключений, обработать исключение и написать минидамп в любом месте. Подробное описание можно найти на Code Project Post-Mortem Debugging Your Application with Minidumps и Visual Studio .NET article.

Убедитесь, что вы создаете отладочную информацию (файлы PDB) для своего приложения в режимах RELEASE (а также отладки). Убедитесь, что вы сохранили набор PDB для каждой выпущенной версии, чтобы вы могли использовать их с дампом. Может быть, использовать локальный сервер символов. Проголосуйте за Suma answer up - он правильный!

Aardvark 25.09.2008 21:18

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

Alex Jenter 26.09.2008 12:00

4) Writig a log shows that the crash happen on a declaration of a local int variable!how could that be? Memory corruption

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

Не могли бы вы уточнить, что такое «сломанный»?

Alex Jenter 26.09.2008 12:03

Алекс, сломанный this похож на ... это: строка ps = новая строка; удалить ps; ps-> clear (). Когда вы войдете внутрь clear (), вы увидите сломанный this.

Constantin 08.10.2008 00:11

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

Спасибо за идею. Как заставить его работать в демонстрационном режиме? Он запрашивает сервер лицензий.

Alex Jenter 26.09.2008 12:01

Скачать пробную версию можно здесь: ibm.com/developerworks/downloads/r/rpp

T.Rob 04.11.2011 22:25

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

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

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

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

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

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

мне нужно сделать это локально на проблемной машине?

Alex Jenter 26.09.2008 12:04

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

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

Думаю, дело не в этом. Это происходило на многих ПК, которые не были разогнаны.

Alex Jenter 26.09.2008 12:09

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

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

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