Каковы эффективные способы отладки оптимизированной программы C/С++?

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

Я использую следующее:

  • Поскольку с ddd вы не видите код, я использую команду gdb + dissambler и вижу полученный код; Я не могу пройти через программу, используя это.
  • ndisasm

Спасибо

Ответы

Ответ 1

Всегда сложнее отлаживать оптимизированные программы, но всегда есть способы. Некоторые дополнительные советы:

  • Создайте сборку отладки и посмотрите, есть ли у вас ошибка в отладочной сборке. Нет смысла отлаживать оптимизированную версию, если вам это не нужно.
  • Используйте valgrind, если на платформе, которая его поддерживает. Ошибки, которые вы видите, могут быть труднее понять, но часто ловить проблему часто упрощает отладку.
  • Отладка printf примитивна, но иногда это самый простой способ, если у вас есть сложная проблема, которая появляется только в оптимизированных сборках.
  • Если вы подозреваете проблему с синхронизацией (особенно в многопоточной программе), сверните свою собственную версию утверждения, которая прерывает или печатает, если это условие нарушено, и использовать его в нескольких выбранных местах, чтобы исключить возможные проблемы.
  • Посмотрите, можете ли вы воспроизвести проблему, не используя -fomit-frame-указатели, поскольку это очень сложно отлаживать код и включать -O2 или -O3. Это может дать вам достаточно информации, чтобы найти причину вашей проблемы.
  • Изолируйте части своего кода, создайте тестовый набор и посмотрите, можете ли вы идентифицировать любые тестовые теги, которые не работают. Гораздо проще отлаживать одну функцию, чем вся программа.
  • Попробуйте отключить оптимизацию один за другим с параметрами -fno-X. Это может помочь вам найти общие проблемы, такие как проблемы с строгим псевдонимом.
  • Включите больше предупреждений компилятора. Некоторые вещи, такие как проблемы с строгим псевдонимом, могут генерировать предупреждения компилятора, если они создают разницу в поведении между различными уровнями оптимизации.

Ответ 2

При отладке релизов вы можете ввести __asm ​​nops; как заполнитель для точек останова (int 3). Это приятно, так как вы можете гарантировать местоположение точек останова, не запутывая оптимизацию компилятора или записывая инструкции printf/cout.

Ответ 3

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

Ответ 4

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

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