Я разрабатываю игру и когда я делаю определенное действие в игре, это отказывает. Таким образом, я пошел, отладив, и я видел свое приложение, разрушенное в простых операторах C++ как if
, return
... Каждый раз, когда я повторно выполняюсь, это отказывает случайным образом в одной из 3 строк, и это никогда не успешно выполняется.
строка 1:
if (dynamic) { ... } // dynamic is a bool member of my class
строка 2:
return m_Fixture; // a line of the Box2D physical engine. m_Fixture is a pointer.
строка 3:
return m_Density; // The body of a simple getter for an integer.
Я не получаю ошибок из приложения, ни ОС...
Есть ли подсказки, подсказки или приемы для отладки более эффективный и известны, что продолжается?
Вот почему я люблю Java...
Спасибо
Подобные случайные сбои обычно вызваны повреждением стека, поскольку это инструкции ветвления и, следовательно, они чувствительны к состоянию стека. Их довольно сложно отследить, но вам следует запускать valgrind и проверять стек вызовов при каждом сбое, чтобы попытаться определить общие функции, которые могут быть основной причиной ошибки.
Просканируйте весь код, сделайте его более понятным, если он непонятен при первом прочтении, попытайтесь понять, что вы написали, и сразу же исправьте то, что кажется неправильным.
Таким образом вы наверняка обнаружите проблему (проблемы) и устраните множество других проблем.
Я обнаружил "случайные" сбои, когда есть некоторые ссылки на удаленный объект. Поскольку память не обязательно перезаписывается, во многих случаях вы не замечаете этого, и программа работает правильно, а затем происходит сбой после того, как память была обновлена и больше не является действительной.
В ЦЕЛЯХ ОБНАРУЖЕНИЯ попробуйте закомментировать некоторые подозрительные 'deletes'. Затем, если он больше не падает, вот и все.
несколько советов:
- запустите приложение в отладчике вместе с файлами символов (PDB).
- Как установить Visual Studio в качестве посмертного отладчика по умолчанию?
- установить отладчик по умолчанию для WinDbg Своевременная отладка
- проверить выделение памяти Переопределение нового и удаления и Переопределение malloc и free
Проверить указатели. Предположительно, вы разыменовываете нулевой указатель.
Еще один трюк: отключите оптимизацию кода и посмотрите, имеют ли точки падения больше смысла. Оптимизация позволяет небольшим кусочкам вашего кода перемещаться в неожиданные места; отображение этого обратно в строки исходного кода может быть не совсем идеальным.
Посмотрите разборку. Практически любой отладчик C / C ++ будет рад показать вам машинный код и регистры, в которых произошел сбой программы. Регистры включают указатель инструкции (EIP или RIP на x86 / x64), где находится программа при остановке. Другие регистры обычно имеют адреса памяти или данные. Если адрес памяти 0 или неправильный указатель, в этом ваша проблема.
Тогда вам просто нужно вернуться назад, чтобы выяснить, как это произошло. Аппаратные точки останова при изменении памяти очень здесь очень полезны.
В Linux / BSD / Mac использование скриптовых функций GDB может здесь очень помочь. Вы можете создать сценарий так, чтобы после 20-кратного срабатывания точки останова это включало аппаратное наблюдение за адресом элемента массива 17. И т.д.
Вы также можете записать отладку в свою программу. Используйте функцию assert ().Где угодно!
Используйте assert для проверки аргументов каждой функции. Используйте assert для проверки состояния каждого объекта перед выходом из функции. В игре подтвердите, что игрок находится на карте, что у игрока есть здоровье от 0 до 100, подтвердите все, что вы можете придумать. Для сложных объектов напишите функции verify () или validate () в сам объект, который проверяет все о нем, а затем вызывает их из assert ().
Другой способ записи в отладке - это заставить программу использовать signal () в Linux или asm int 3 в Windows для взлома отладчика из программы. Затем вы можете записать в программу временный код, чтобы проверить, находится ли он на итерации 1117321 основного цикла. Это может быть полезно, если ошибка всегда возникает на 1117322. Таким образом программа будет выполняться намного быстрее, чем при использовании точки останова отладчика.
У меня раньше были подобные проблемы. Я пытался обновить графический интерфейс из разных потоков.
Простых операторов C ++ не существует. Условие «если» настолько просто, насколько просто оцениваемое вами условие. Возврат так же прост, как возвращаемое вами выражение.
Вы должны использовать отладчик и / или опубликовать код, который приводит к сбою. Не может быть много пользы, если в качестве информации указано «мое приложение разбилось».
Сбои / сбои сегментов обычно происходят, когда вы обращаетесь к участку памяти, к которому он не имеет доступа, или когда вы пытаетесь получить доступ к области памяти недопустимым способом (например, пытаетесь для записи в место только для чтения).
Есть много инструментов для анализа памяти, например, я использую Valgrind, который действительно отлично показывает, в чем проблема (не только номер строки, но и то, что вызывает сбой).
Мне обычно нравится делать шаг назад и обдумывать код, пытаясь уловить любые логические ошибки.
Вы можете попробовать закомментировать различные части кода и посмотреть, повлияет ли это на компиляцию программы.
Помимо этих двух вещей, вы можете попробовать использовать отладчик, например Visual Studio или Eclipse и т.д..
Наконец, вы можете попробовать опубликовать свой код и ошибку, которую вы получаете, на сайте с сообществом, которое разбирается в программировании и может помочь вам разобраться с ошибкой (читай: stackoverflow)
.Есть ли подсказки, советы или приемы, чтобы отлаживать более эффективно и узнать, что происходит?
В целом, вы должны быть счастливы, что приложение где-то падает. Авария означает ошибку, которую можно быстро найти с помощью отладчика и уничтожить. Баги, не приводящие к краху программы, гораздо сложнее (пример действительно сложного бага: при 100000 значений входных данных, после нескольких сотен манипуляций со значениями, среди тысяч выходных, приложение выдает 1 абсолютно неверный результат, которого вообще не должно было быть)
Вот почему я люблю Java...
Извините, если вы не можете справиться с языком, это полностью ваша вина. Если вы не можете справиться с инструментом, либо выберите другой, либо улучшите свои навыки. На java можно сделать игру, кстати.
Если в операторах if
происходит разыменование указателей, вы почти наверняка повреждаете стек (это объясняет, почему невинный return 0
приводит к краху...)
Это может произойти, например, при выходе за границы массива (вы должны использовать std::vector
! ), при попытке strcpy
строки, основанной на char[]-строке, в которой отсутствует окончание '\0'
(следует использовать std::string
!), при передаче неверного размера в memcpy
(следует использовать конструкторы копирования!) и т.д.
Попробуйте найти способ надежно воспроизвести это, а затем установите наблюдение за поврежденным указателем. Пробегитесь по коду построчно, пока не найдете ту самую строку, которая повреждает указатель.
В основном это происходит из-за повреждения стека, но повреждение кучи также может таким образом повлиять на программы.
Повреждение стека чаще всего происходит из-за «ошибки смещения на единицу».
Повреждение кучи происходит из-за того, что команда new / delete не обрабатывается должным образом, как, например, двойное удаление.
Обычно происходит то, что переполнение / повреждение перезаписывает важную инструкцию, а потом, намного позже, когда вы пытаетесь выполнить инструкцию, она вылетает.