Распространенные причины ошибок в версии выпуска отсутствуют в режиме отладки - PullRequest
63 голосов
/ 19 ноября 2009

Каковы типичные причины ошибок и ненормального поведения программы, которые проявляются только в режиме компиляции релиза, но не возникают в режиме отладки?

Ответы [ 18 ]

30 голосов
/ 19 ноября 2009

Во многих случаях в режиме отладки в C ++ все переменные инициализируются нулем, тогда как в режиме выпуска это не происходит, если явно не указано.

Проверка на наличие макросов отладки и неинициализированных переменных

Если ваша программа использует многопоточность, то оптимизация также может вызвать некоторые проблемы в режиме выпуска.

Также проверьте все исключения, например, не связанные напрямую с режимом выпуска, но иногда мы просто игнорируем некоторые критические исключения, такие как нарушение доступа к mem в VC ++, но это может быть проблемой, по крайней мере, в других ОС, таких как Linux, Solaris. В идеале ваша программа не должна перехватывать такие критические исключения, как доступ к NULL-указателю.

19 голосов
/ 19 ноября 2009

Типичной ошибкой является использование выражения с побочным эффектом внутри ASSERT.

9 голосов
/ 19 ноября 2009

Другие различия могут быть:

  • На языке для сбора мусора коллекционер обычно более агрессивен в режиме разблокировки;
  • Расположение памяти может часто быть разными;
  • Память может быть инициализируется по-другому (например, может быть обнуляется в режиме отладки или используется повторно агрессивно в выпуске);
  • Местные жители могут повышаться для регистрации значений в выпуске, который может вызвать проблемы с плавающей запятой значения.
6 голосов
/ 11 мая 2010

В прошлом меня укусило множество ошибок, которые исправлялись в сборках Debug, но приводили к сбоям в сборках Release. Есть много основных причин (включая, конечно, те, которые уже были обобщены в этой теме), и я был обнаружен всем следующим:

  • Переменные-члены или функции-члены в #ifdef _DEBUG, так что класс в отладочной сборке имеет другой размер. Иногда #ifndef NDEBUG используется в сборке релиза
  • Точно так же есть другая #ifdef, которая присутствует только в одной из двух сборок
  • Отладочная версия использует отладочные версии системных библиотек, особенно функции кучи и выделения памяти
  • Встроенные функции в сборке выпуска
  • Порядок включения заголовочных файлов. Это не должно вызывать проблем, но если у вас есть что-то вроде #pragma pack, которое не было сброшено, то это может привести к неприятным проблемам. Подобные проблемы могут также возникать при использовании предварительно скомпилированных заголовков и принудительного включения
  • Кеши: у вас может быть такой код, как кеши, которые используются только в сборках релиза, или другие ограничения размера кеша
  • Конфигурации проекта: конфигурации отладки и выпуска могут иметь разные параметры сборки (это может произойти при использовании IDE)
  • Условия гонки, проблемы с синхронизацией и различные побочные эффекты, возникающие в результате отладки только кода

Несколько советов, которые я накопил за эти годы, чтобы докопаться до ошибок отладки / выпуска:

  • Попробуйте воспроизвести аномальное поведение в отладочной сборке, если вы можете, и даже лучше, написать модульный тест, чтобы перехватить его
  • Подумайте о том, что отличается между ними: настройки компилятора, кэши, код только для отладки. Попробуйте временно минимизировать эти различия
  • Создайте сборку выпуска с отключенными оптимизациями (чтобы вы с большей вероятностью получили полезные данные в отладчике) или оптимизированную сборку отладки. Минимизируя изменения между отладкой и выпуском, вы с большей вероятностью сможете определить, какая разница вызывает ошибку.
3 голосов
/ 19 ноября 2009

Функции библиотеки CRT ведут себя по-разному в отладке по сравнению с выпуском (/ MD vs /MDd).

Например, версии отладки часто предварительно заполняют буферы, которые вы передаете на указанную длину, чтобы проверить вашу заявку. Примеры включают strcpy_s, StringCchCopy и т. Д. Даже если строки заканчиваются раньше, ваш szDest лучше иметь n байт в длину!

3 голосов
/ 19 ноября 2009

Может, особенно если вы находитесь в мире C.

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

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

РЕДАКТИРОВАТЬ: я вижу другие упоминал это: конечно, вы могли бы иметь целые разделы кода, которые условно исключены, если не компилируются в режиме отладки. Если это так, я надеюсь, что это действительно отладочный код, а не что-то жизненно важное для правильности самой программы!

3 голосов
/ 19 ноября 2009

Да !, если у вас есть условная компиляция, могут быть ошибки синхронизации (стих с оптимизированным кодом выпуска, неоптимизированный код отладки), повторное использование памяти и куча отладки.

2 голосов
/ 19 ноября 2009

Конечно, если вы используете такие конструкции, как

#if DEBUG

//some code

#endif
2 голосов
/ 19 ноября 2009

В .NET, даже если вы не используете условную компиляцию, такую ​​как #if DEBUG, компилятор все еще более либерален с оптимизацией в режиме выпуска, чем в режиме отладки, что также может привести к выпуску только ошибок.

1 голос
/ 07 апреля 2013

В непустой функции все пути выполнения должны заканчиваться оператором возврата.

В режиме отладки, если вы забыли завершить такой путь с помощью оператора return, функция обычно возвращает 0 по умолчанию.

Однако в режиме выпуска ваша функция может возвращать значения мусора, которые могут повлиять на работу вашей программы.

...