Как определить, где программа застряла в бесконечном цикле? - PullRequest
3 голосов
/ 15 июля 2011

Я работаю над (относительно сложной) игрой.Игра зависает в режиме релиза.Замораживание происходит через 1-2 мин.геймплея.Текущая конфигурация режима выпуска, которую я имею, позволяет мне нарушить (то есть перейти в отладку), что хорошо, но может дать мне неверную информацию, но это хорошо для этого конкретного случая (я могу отключить оптимизацию для одногофайл / функция / код).

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

Первое, что я попробовал, это break all Visual Studio, но он всегда ломается в коде, который мне не принадлежит, и, следовательно, показывает мне вывод сборки.В конце концов, с достаточной настойчивостью, проверяя историю SVN и комментируя код, я смогу выяснить, где она висит, но должен быть лучший способ ... надеюсь?

Примечание: Существует известная мне опция Visual Studio, которая позволяет отлаживать только код пользователя , но это только управляемый код.

РЕДАКТИРОВАТЬ: Был в состоянии решить проблему с помощью трассировки стека и много часов отслеживания различных вещей, чтобы увидеть, где игра висит .Я выберу правильный ответ Шёрда, однако, если у кого-то есть предложение по инструменту / технике, которая позволяет автоматизировать такую ​​задачу, во что бы то ни стало, добавьте свой ответ!

Ответы [ 4 ]

3 голосов
/ 15 июля 2011

Если вы сломаете и обнаружите собственный код, который не принадлежит вам, проверьте стек вызовов . Стек вызовов - это список функций, которые были вызваны для достижения текущей точки в коде. Поднимитесь на несколько уровней в стеке, пока не встретите метод, который в данный момент выполняется.

2 голосов
/ 15 июля 2011

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

1 голос
/ 15 июля 2011

Вы, возможно, никогда не сможете обнаружить проблему с помощью прерывания, если код, который должен выполняться, не выполняется. Есть много способов, которыми это может произойти. Всего несколько:

  • У вас есть некоторый параметр, который указывает время, когда должно быть выполнено следующее обновление. Если это так или иначе установлено в какое-то большое число, код, который выполняет обновление, с радостью увидит, что ничего не нужно делать. Следующий! Это может дать все виды зависшей программы, даже если она вообще не зависла. Обновление состояния и графические функции по-прежнему вызываются с установленной скоростью.

  • Вы можете использовать некоторый счетчик, который представляет время, и некоторый механизм округления для увеличения времени. Если счетчик представляет собой 32-разрядное целое число со знаком и гранулярность вашего счетчика составляет 0,1 микросекунды, вы нажмете INT32_MAX всего за 3,6 минуты. Теперь время заморожено, поэтому снова возникает ситуация, когда обновления могут не выполняться.

  • Вы используете число с плавающей запятой одинарной точности для представления времени и времени обновления с помощью time += delta_t; Это перестанет работать через пару минут, если ваш delta_t равен 10 микросекундам. Это еще один механизм, с помощью которого можно заморозить время.

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

1 голос
/ 15 июля 2011

Нажмите кнопку паузы в Visual Studio, когда программа зависла.

Это должно привести к поломке отладчика в текущей строке.Затем вы можете пройти и посмотреть, что происходит.

...