RNG сбой программы C ++ - PullRequest
       46

RNG сбой программы C ++

1 голос
/ 05 апреля 2011

Я в настоящее время кодирую roguelike и, естественно, использую много генераций случайных чисел.

Проблема, с которой я сталкиваюсь, заключается в том, что если я "перегрею" rand ();моя программа вылетит.

Если я генерирую только 20 или около того целых чисел за кадр, это нормально ... но когда количество случайных чисел исчисляется сотнями, программа вылетает.Чем больше я создаю каждый кадр, тем быстрее он падает, что приводит меня к мысли, что происходит какое-то нагромождение.

Я провел тесты, и на 20 rand ();звонки в кадре, он будет работать 24 часа подряд на максимальной скорости без сбоев.Это утроить, и это не займет десять минут.

Если я поставлю srand ();в инициализации я могу производить тысячи случайных чисел, прежде чем они заблокируются - но если я добавлю srand ();в самом кадре я делаю примерно 2-8 кадров.Если это имеет значение, я использую время (ноль) для затравки.

чем чаще я вызываю rand ();чем раньше он рухнет.

Помощь?

Ответы [ 5 ]

1 голос
/ 05 апреля 2011

Функция rand () не является реентерабельной или поточно-ориентированной, поскольку использует скрытое состояние, которое изменяется при каждом вызове. Это может быть просто начальное значение использовать следующий вызов, или это может быть что-то более сложное. Чтобы получить воспроизводимое поведение в многопоточном приложении, это состояние должно быть явным Функция rand_r () снабжена указателем на unsigned int, который будет использоваться как состояние. Это очень небольшое количество государства, поэтому эта функция будет слабым псевдослучайным генератором. Попробуйте вместо этого drand48_r (3).

0 голосов
/ 05 апреля 2011

Несколько комментариев и идей о том, как сузить источник проблемы:

  • Это почти наверняка не функции srand() или rand(), вызывающие сбой / блокировку.Скорее всего, одна или несколько комбинаций случайных чисел приводят ваш двигатель в состояние, в котором происходит что-то плохое.
  • Первым шагом должно стать дублирование проблемы, чтобы она всегда происходила в определенное время.Вместо использования srand(NULL) попробуйте использовать постоянное начальное число, например srand(12345).В зависимости от того, какие другие факторы использует ваш движок (например, пользовательский ввод), этого может быть достаточно, чтобы каждый раз происходить сбой в одном и том же месте.
  • Если при использовании отладчика возникают проблемы (что подозрительно, возможно, буфер)переполнение приводит к повреждению стека) используйте проверенный метод вывода сообщений в текстовый файл журнала.Я бы предложил вывести все сгенерированные случайные числа, и, возможно, вы можете увидеть шаблон, когда он падает (то есть он падает всякий раз, когда генерируется «42»).Другой вариант - начать добавление нескольких сообщений журнала в различные функции (начните с функций высокого уровня, таких как цикл обновления игры).После сбоя проверьте журнал и начните добавлять другие сообщения журнала, пока вы не сузите его до одной строки / функции.Это не так быстро, как использование отладчика, но иногда это лучший выбор, особенно если вы не знаете, с чего начать.
  • Как только вы сможете надежно воспроизвести сбой, начните удалять вещи, покаточка сбоя меняется или исчезает.Это может включать #ifdef s, комментирование кода, настройку параметров приложения или даже создание временной копии проекта, чтобы вы могли просто удалить код, скомпилировать и протестировать.Это может быть сложно, если проект большой / сложный.
  • Дополнительная информация о типе "сбоя" будет полезна.Обычно программы не просто аварийно завершают работу, но имеют место определенные исключения, блокировки и т. Д. Сведения об исключениях могут помочь вам с некоторым трудом сузить источник проблемы.
0 голосов
/ 05 апреля 2011
  1. Вы, вероятно, не должны использовать rand ().Есть намного лучшие PRNGs там.Взгляните на Boost.Random.
  2. Вы должны srand () только один раз, а не каждый кадр.
  3. Узнайте, где происходит сбой вашего кода.Используя довольно простой отладчик, просто запустите программу с подключенным отладчиком и подождите, пока он не выйдет из строя.
  4. После того, как вы узнаете, где он падает, выясните причину его сбоя.выяснили почему, почините.Вероятно, это не имеет ничего общего с rand ().
0 голосов
/ 05 апреля 2011

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

0 голосов
/ 05 апреля 2011

Попробуйте запустить его под отладчиком

$ gdb myprog
(gdb) break main
(gdb) run
(gdb) record

, например

(gdb) break abort
(gdb) break exit

, поскольку это C ++:

(gdb) catch throw
(gdb) catch exception

и наконец (GDB) продолжить

Когда он остановится, продолжайте движение в обратном направлении, пока не найдете виновного


Вариант 2:

valgrind --tool=massif --massif-out-file="massif.out.%p" myprog
ms_print massif.out.*

для проверки профилирования кучи. Не исключено, что у вас утечка памяти

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...