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





Большинство ошибок heisenbugs / релизов связано либо с потоком управления, который зависит от чтения из неинициализированной памяти / устаревшими указателями / с конца буферов, либо с условиями гонки, либо с обоими.
Попробуйте переопределить свои распределители, чтобы они обнуляли память при распределении. Проблема исчезнет (или станет более воспроизводимой?)
Writig a log shows that the crash happens on a declaration of a local int variable! How could that be? Memory corruption?
Переполнение стека! ;)
Спасибо за идею, обязательно вернусь в этом направлении
Значит, при настройке 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 указал мне на это. Но, к сожалению, это изменение не повлияло на ошибку.
Для меня это звучит как разрушение стека. Мой любимый инструмент для их отслеживания - IDA Pro. Конечно, у вас нет доступа к машине пользователя.
Некоторым программам проверки памяти трудно обнаружить повреждение стека (если это действительно так). Я считаю, что самый надежный способ получить их - это анализ во время выполнения.
Это также может быть связано с повреждением пути исключения, даже если исключение было обработано. Вы выполняете отладку с включенной функцией «ловить первоочередные исключения»? Вы должны так долго, как можете. Через некоторое время во многих случаях это действительно начинает раздражать.
Можете ли вы отправить этим пользователям проверенную версию вашего приложения? Проверьте Минидамп Обработайте это исключение и запишите дамп. Затем используйте WinDbg для отладки на вашей стороне.
Другой метод - ведение очень подробных журналов. Создайте параметр «Записывать каждое действие» и попросите пользователя включить его и отправить вам. Выгрузить память в логи. Посмотрите «_CrtDbgReport ()» в MSDN.
Удачи!
Обновлено:
Отвечая на ваш комментарий: Меня не удивляет ошибка в объявлении локальной переменной. Я видел это много раз. Обычно это происходит из-за поврежденного стека.
Например, некоторая переменная в стеке может выходить за его границы. После этого начинается ад. Затем объявления переменных стека вызывают случайные ошибки памяти, виртуальные таблицы повреждаются и т. д.
Каждый раз, когда я видел их в течение длительного периода времени, мне приходилось переходить на IDA Pro. Подробная отладка дизассемблирования во время выполнения - единственное, что я знаю, что действительно надежно их получает.
Многие разработчики используют WinDbg для такого рода анализа. Вот почему я также предложил Minidump.
Спасибо за все идеи. Я уже написал журнал, и он указывал на объявление переменной типа int. Я не шучу, код был такой: log << "before"; log.flush (); int i; журнал << "после"; log.flush (); - и только «до» было в лог-файле.
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 - это требует немного денег (вам нужен идентификатор для подписи цифрового кода) и некоторого заполнения формы. Для получения дополнительной информации посетите https://winqual.microsoft.com/.
Другой вариант - связаться с каким-либо пользователем, у которого произошел сбой, и получить аварийный дамп, предназначенный для WER, напрямую от него. Пользователь может сделать это, щелкнув «Технические подробности» перед отправкой сбоя в Microsoft - там можно проверить расположение файла аварийного дампа.
Другой вариант - зарегистрировать собственный обработчик исключений, обработать исключение и написать минидамп в любом месте. Подробное описание можно найти на Code Project Post-Mortem Debugging Your Application with Minidumps и Visual Studio .NET article.
Убедитесь, что вы создаете отладочную информацию (файлы PDB) для своего приложения в режимах RELEASE (а также отладки). Убедитесь, что вы сохранили набор PDB для каждой выпущенной версии, чтобы вы могли использовать их с дампом. Может быть, использовать локальный сервер символов. Проголосуйте за Suma answer up - он правильный!
Спасибо, попробую последнюю идею с минидампом. К сожалению, я не привык к низкоуровневой отладке, поэтому мне нужно прочитать об этом подробнее ...
4) Writig a log shows that the crash happen on a declaration of a local int variable!how could that be? Memory corruption
Я обнаружил, что причиной многочисленных «странных сбоев» является разыменование сломанного this внутри функции-члена указанного объекта.
Не могли бы вы уточнить, что такое «сломанный»?
Алекс, сломанный this похож на ... это: строка ps = новая строка; удалить ps; ps-> clear (). Когда вы войдете внутрь clear (), вы увидите сломанный this.
Попробуйте Rational (IBM) PurifyPlus. Он выявляет множество ошибок, которых нет в BoundsChecker.
Спасибо за идею. Как заставить его работать в демонстрационном режиме? Он запрашивает сервер лицензий.
Скачать пробную версию можно здесь: ibm.com/developerworks/downloads/r/rpp
Что говорит авария? Нарушение доступа ? Исключение ? Это будет еще одним ключом к решению этой проблемы с помощью
Убедитесь, что у вас нет предшествующих повреждений памяти с помощью PageHeap.exe
Убедитесь, что у вас нет переполнения стека (массив CBig [1000000])
Убедитесь, что у вас нет неинициализированной памяти.
Кроме того, вы можете запустить версию выпуска также внутри отладчика, как только вы сгенерируете символы отладки (не такие, как создание отладочной версии) для процесса. Пройдите дальше и посмотрите, не появляются ли предупреждения в окне трассировки отладчика.
Загрузите пакет Инструменты отладки для Windows. Правильно задайте пути к символам, затем запустите приложение под WinDbg. В какой-то момент он сломается с нарушением доступа. Затем вы должны запустить команду "! Анализировать -v", которая довольно умна и должна подсказать вам, что происходит не так.
мне нужно сделать это локально на проблемной машине?
«4) Запись журнала показывает, что сбой происходит при объявлении локальной переменной типа int! Как это могло быть? Повреждение памяти?»
Это может быть признаком того, что оборудование действительно неисправно или слишком сильно нагружено. Узнайте, разогнали ли они свой компьютер.
Думаю, дело не в этом. Это происходило на многих ПК, которые не были разогнаны.
Когда я получаю такие вещи, я пытаюсь запустить код через gimpels PC-Lint (статический анализ кода), поскольку он проверяет различные классы ошибок в BoundsChecker. Если вы используете Boundschecker, включите параметры отравления памяти.
Вы упомянули процессоры AMD. Вы исследовали, есть ли аналогичная версия видеокарты / драйвера и / или конфигурация на машинах, которые дают сбой? На этих машинах он всегда дает сбой или только время от времени? Может быть, запустите инструмент системной информации на этих машинах и посмотрите, что у них общего,
Похоже, что золотое сечение было ближе всего к ответу.