Почему некоторые вещи никогда не ломаются при включенном отладчике? - PullRequest
4 голосов
/ 02 августа 2010

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

The multi-thread debug CRT (/MTd) masks the problem, because, like

Windows делает с процессами, порожденными отладчик, он предоставляет вашему запрограммировать кучу отладки, то есть инициализируется в шаблон 0xCD. Вероятно, где-то вы используете некоторые неинициализированная область памяти от куча как указатель и вы разыграете Это; с двумя кучами отладки вы получаете покончить с этим по какой-то причине (может быть, потому что по адресу 0xbaadf00d и 0xcdcdcdcd там действительно выделено память), но с "нормальной" кучей (который часто инициализируется в 0) вы получить нарушение доступа, потому что вы разыменовывать нулевой указатель.

Проблема в том, что происходит сбой в GLU32.dll, и я не могу выяснить, почему он иногда пытается разыменовать нулевой указатель. кажется, это происходит, когда мои многоугольники становятся довольно большими и имеют много точек. Что я могу сделать?

Спасибо

Ответы [ 3 ]

3 голосов
/ 02 августа 2010

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

Вы можете попробовать вручную инициализировать кучу другим значением (или посмотреть, есть ли опциядля этого в Visual Studio).Обычно инициализация, отличная от нуля, фиксирует больше ошибок, но в вашей ситуации это может быть не так.Вы также можете попробовать поиграть с отображением памяти вашей программы, чтобы убедиться, что страница 0xcdcdc000 не отображена.

Visual Studio может установить точку останова при доступе к определенному адресу памяти, вы можете попробовать это (это может замедлить вашу программузначительно больше, чем переменная точка останова).

2 голосов
/ 02 августа 2010

Ссылка на предыдущий вопрос и две мысли.

Прежде всего вы можете захотеть взглянуть на предыдущий вопрос о заменителях valgrind для окон.Много хороших советов о программах, которые помогут вам.

Теперь подумайте:

1) Отладчик может предотвратить сбой вашей программы в тестируемом коде, но это не решает проблему.В худшем случае вы просто пинаете банку по улице, коррупция все еще существует, но это не видно по тому, как вы бежите.Когда вы отправляете, вы можете быть уверены, что кто-то снова столкнется с проблемой.

2) В таких случаях часто случается так, что ошибка не рядом с местом возникновения проблемы.Хотя вы, возможно, замечали проблему в GLU32.dll, возможно, раньше было повреждение, возможно, даже в другом потоке или функции, которое не вызывало проблемы, и в какой-то момент позже программа вернулась в поврежденную область и не удалось.

2 голосов
/ 02 августа 2010

но он никогда не падает, если я начинаю отладку в VS.

Ну, я не совсем уверен, , почему , но при отладке в программе Visual Studio иногда может сойти с доступа к некоторым областям памяти, которые могут привести к сбою без отладчика. Хотя я не знаю точных причин, но иногда 0xcdcdcdcd и 0xbaadfood не имеют к этому никакого отношения. Просто доступ к определенным адресам не вызывает проблем. Когда это произойдет, вам нужно будет найти альтернативные методы угадывания проблемы.

Что я могу сделать?

Возможные решения:

  1. Установить обработчик исключений в вашей программе ( _set_se_translator , если я правильно помню). При нарушении доступа попробуйте MinidumpWriteDump . Отладьте его позже, используя Visual Studio (afaik, отладка аварийного дампа недоступна в экспресс-выпуске) или windbg.
  2. Используйте отладчики, работающие точно в срок. Неэкспресс-издание Visual Studio имеет эту функцию. Есть, вероятно, альтернативы.
  3. Напишите пользовательский менеджер памяти (который переопределит new / delete и предоставит альтернативы malloc / free (если вы их используете)), который захватит большой кусок памяти, заблокирует всю неиспользуемую память с помощью VirtualProtect . В этом случае любой недопустимый доступ вызовет сбои даже в режиме отладки. Для такого менеджера памяти вам потребуется много памяти, потому что для блокировки каждый блок должен быть выровнен по страницам.
  4. Добавить чрезмерное ведение журнала всем подозрительным вызовам функций. Скопируйте много текстовой / отладочной информации в файл (или stderr) - значения параметров, массивы, все, что вы подозреваете, может быть связано с сбоем, сбрасывать после каждой записи в файл, иначе некоторая информация будет потеряна во время сбоя. Таким образом, вы сможете угадать, что произошло до сбоя программы.
  5. Попробуйте отладить сборку релиза. Вы должны быть в состоянии сделать это до некоторой степени, если вы включите «отладочную информацию» для сборки релиза в настройках проекта.
  6. Попробуйте включить / выключить «базовые проверки времени выполнения» и «проверку безопасности буфера» в свойствах проекта (configuration properties->c/c++->code genration).
  7. Попробуйте найти какой-нибудь внешний инструмент - что-то вроде valgrind или bounds checker. Хотя, к моему опыту, № 3 более надежен, чем этот подход. Хотя это действительно зависит от проблемы.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...