1

我目前正在编写 roguelike,自然会使用大量随机数生成。

我遇到的问题是,如果我“过热” rand(); 我的程序会崩溃。

如果我每帧只生成 20 个左右的整数,那很好……但是当随机数的数量达到数百个时,程序就会崩溃。我制作每一帧的次数越多,崩溃的速度就越快……这让我相信发生了一些堆积。

我已经完成了测试,并且在 20 rand(); 每帧调用一次,它将以最大速度连续运行 24 小时而不会崩溃。三倍,它没有十分钟。

如果我把 srand(); 在初始化中,我可以在锁定之前生成数千个随机数 - 但如果我输入 srand(); 在框架本身内,我制作了大约 2-8 帧。如果重要的话,我正在使用 time(null) 来播种。

我调用 rand() 的频率越高;它越早崩溃。

帮助?

4

5 回答 5

1

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

于 2011-04-04T21:33:19.453 回答
0

尝试在调试器下运行它

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

检查堆分析。你不太可能有内存泄漏

于 2011-04-04T21:55:33.307 回答
0

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

于 2011-04-04T22:02:55.710 回答
0
  1. 您可能不应该使用 rand()。那里有更好的 PRNG。看看 Boost.Random。
  2. 您应该只 srand() 一次,而不是每一帧。
  3. 找出你的代码在哪里崩溃。使用相当简单的调试器,只需启动带有调试器的程序并等待它崩溃。
  4. 在你找到它崩溃的地方之后,找出它崩溃的原因。
  5. 找出原因后,修复它。它可能与 rand() 没有任何关系。
于 2011-04-04T22:13:11.663 回答
0

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

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