RNG崩溃的c ++程序

时间:2011-04-04 21:28:12

标签: c++ random overflow srand

我目前正在编写一个roguelike,自然而然地使用了大量随机数。

我正在运行的问题是,如果我“过热”rand();我的程序会崩溃。

如果我每帧只生成20个左右的内容,那很好......但是当随机数量达到数百个时,程序崩溃了。我越是产生每一帧,它越早崩溃......这让我相信有一些堆积。

我已经完成了测试,并且在20兰特();每帧呼叫,它将以最大速度直接运行24小时而不会崩溃。三倍,它不会使它十分钟。

如果我把srand();在初始化中,我可以在它锁定之前生成数千个随机数 - 但是如果我把srand();在框架内部,我使它大约2-8帧。如果重要,我会用时间(null)来播种。

我越频繁地调用rand();它越早崩溃。

帮助?

5 个答案:

答案 0 :(得分:1)

  

函数rand()不是可重入的或线程安全的,因为它使用在每次调用时修改的隐藏状态。这可能只是种子价值      被下一个电话使用,或者它可能更精细。为了在线程应用程序中获得可重现的行为,此状态必须      明确。函数rand_r()提供了一个指向unsigned int的指针,用作状态。这是一个非常少量的国家,      所以这个函数将是一个弱伪随机生成器。请尝试drand48_r(3)。

答案 1 :(得分:0)

尝试在调试器

下运行它
$ gdb myprog
(gdb) break main
(gdb) run
(gdb) record

e.g。

(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.*

检查堆分析。你不会有内存泄漏

答案 2 :(得分:0)

rand的大量调用可能会出现一个代码无法处理的相对较小范围内的数字。尝试使用只增加数字并返回数字的函数替换对rand的调用,并查看它是否最终失败。

答案 3 :(得分:0)

  1. 你很可能不应该使用rand()。那里有更好的PRNG。看看Boost.Random。
  2. 你应该只对srand()进行一次,而不是每一帧。
  3. 找出代码崩溃的位置。使用相当简单的调试器,只需在附加调试器的情况下启动程序,然后等待它崩溃。
  4. 找到崩溃的地方后,找出崩溃的原因。
  5. 找到原因后,解决它。它可能与rand()没有任何关系。

答案 4 :(得分:0)

关于如何缩小问题根源的一些意见和想法:

  • 几乎可以肯定的是srand()rand()函数导致崩溃/锁定。有可能是随机数的一个或多个组合使您的引擎进入发生不良事件的状态。
  • 第一步应该是复制问题,使其始终在时间/地点发生。而不是使用srand(NULL)尝试使用像srand(12345)这样的常量种子。根据您的引擎使用的其他因素(如用户输入),这可能足以让它每次都在相同的位置崩溃。
  • 如果使用调试器有问题(可能是缓冲区溢出正在破坏堆栈),请使用经过验证的方法将消息输出到文本日志文件。我建议输出所有生成的随机数,也许你可能会在崩溃时看到一个模式(即每当产生“42”时它会崩溃)。另一个选择是开始在各种功能中添加一些日志消息(从高级功能开始,如游戏更新循环)。崩溃后检查日志并开始添加更多日志消息,直到将其缩小到一行/功能。这不像使用调试器那么快,但有时候是更好的选择,特别是如果你真的不知道从哪里开始寻找。
  • 一旦您能够可靠地复制崩溃,就会开始删除事物,直到崩溃点发生变化或消失。这可能涉及#ifdef,注释掉代码,设置应用程序选项,甚至创建项目的临时副本,以便您可以简单地删除代码,编译和测试。如果项目很大/很复杂,这可能很难。
  • 有关“崩溃”类型的更多信息会很有帮助。通常程序不仅会崩溃,而且会发生某些异常,锁定等等。例外细节可以帮助您通过一些努力缩小问题的根源。