简体   繁体   English

RNG崩溃的C ++程序

[英]RNG crashing c++ program

I am currently coding a roguelike, and naturally am using a lot of random number generation. 我目前正在编码“流氓”游戏,并且自然会使用大量随机数生成器。

The problem I'm running up on is that if I "overheat" rand(); 我遇到的问题是,如果我“过热” rand(); my program will crash. 我的程序将崩溃。

If i'm only generating 20 or so ints per frame, it's fine... but when the amount of random numbers goes into the hundreds, the program crashes. 如果我每帧仅生成20个左右的整数,就可以了……但是,当随机数达到数百时,程序崩溃。 The more I'm producing every frame, the sooner it crashes... which leads me to believe there is some pileup going on. 我生产的每个帧越多,它崩溃的时间就越早……这使我相信会有一些堆积。

I've done tests, and at 20 rand(); 我已经做过测试,并且是20 rand(); calls per frame, it will run for 24 hours straight at max speed without crashing. 每帧调用一次,它将以最大速度连续运行24小时而不会崩溃。 Triple that and it doesn't make it ten minutes. 将其增加三倍,它不会十分钟。

If I put srand(); 如果我放srand(); in the initialization, i can churn out thousands of random numbers before it locks up - but if I put srand(); 在初始化中,我可以在锁定之前删除成千上万的随机数-但是如果我放srand(); within the frame itself, i make it about 2-8 frames. 在框架本身内,我使其大约2-8帧。 If it matters, I'm using time(null) to seed. 如果重要的话,我正在使用时间(空)作为种子。

the more frequently i call rand(); 我调用rand()的频率越高; the sooner it crashes. 它越早崩溃。

Help? 救命?

The function rand() is not reentrant or thread-safe, since it uses hidden state that is modified on each call. 函数rand()不可重入也不是线程安全的,因为它使用在每次调用时都会修改的隐藏状态。 This might just be the seed value to be used by the next call, or it might be something more elaborate. 这可能只是下一个调用要使用的种子值,或者可能更复杂。 In order to get reproducible behavior in a threaded application, this state must be made explicit. 为了在线程化应用程序中获得可重现的行为,必须使此状态明确。 The function rand_r() is supplied with a pointer to an unsigned int, to be used as state. 函数rand_r()提供了一个指向无符号int的指针,该指针将用作状态。 This is a very small amount of state, so this function will be a weak pseudo-random generator. 这是非常少量的状态,因此此函数将是一个弱伪伪生成器。 Try drand48_r(3) instead. 尝试改用drand48_r(3)。

Try running it under a debugger 尝试在调试器下运行它

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

eg 例如

(gdb) break abort
(gdb) break exit

since it is c++: 由于它是c ++:

(gdb) catch throw
(gdb) catch exception

and finally (gdb) continue 最后(gdb)继续

When it stops, reverse-continue until you find the culprit 停止时,反向继续直到找到罪魁祸首


Option 2: 选项2:

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

to examine heap profiling. 检查堆分析。 Not unlikely you have a memory leak 不太可能出现内存泄漏

It's possible the high number of calls to rand are coming up with a number in a relatively small range which your code cannot handle. 可能有大量的rand调用会导致代码无法处理的相对较小的数字。 Try replacing your calls to rand with a function that just increments a number and returns it, and see if it eventually fails. 尝试用仅增加数字并返回数字的函数替换对rand的调用,然后查看它是否最终失败。

  1. You probable shouldn't be using rand(). 您可能不应该使用rand()。 There are far better PRNGs out there. 那里有更好的PRNG。 Have a look at Boost.Random. 看看Boost.Random。
  2. You should only srand() once, not every frame. 您只应该对srand()进行一次,而不是每帧一次。
  3. Find out where your code crashes. 找出代码崩溃的地方。 Using a debugger that's fairly easy, just start the program with the debugger attached and wait until it crashes. 使用非常简单的调试器,只需在连接了调试器的情况下启动程序,然后等待其崩溃即可。
  4. After you have found out where it crashes, find out why it crashes. 找到崩溃的原因之后,请找出崩溃的原因。
  5. After you have found out why, fix it. 找到原因后,进行修复。 It probably doesn't have anything to do with rand(). 它可能与rand()没有任何关系。

A few comments and ideas on how to narrow down the source of the issue: 关于如何缩小问题来源的一些意见和想法:

  • It almost certainly is not the srand() or rand() functions causing the crash/lock up. 几乎可以肯定不是导致崩溃/锁定的srand()rand()函数。 Chances are that one, or more, combinations of random numbers is getting your engine into a state where something bad happens. 一个或多个随机数的组合可能会使您的引擎进入发生不良情况的状态。
  • The first step should be to duplicate the issue such that it always happens at the time/place. 第一步应该是复制问题,使其始终在时间/地点发生。 Instead of using a srand(NULL) try using a constant seed like srand(12345) . 而不是使用srand(NULL)尝试使用像srand(12345)这样的常量种子。 Depending on what other factors your engine uses (like user input) this may be enough to get it to crash in the same spot each time. 根据引擎使用的其他因素(例如用户输入),这足以使它每次都崩溃在同一位置。
  • If using the debugger is having issues (which is suspect, perhaps a buffer overflow is corrupting the stack) use the tried and true method of outputting messages to a text log file. 如果使用调试器时遇到问题(怀疑,可能是缓冲区溢出正在破坏堆栈),请使用将消息输出到文本日志文件的可靠方法。 I would suggest outputting all the random numbers generated and perhaps you may see a pattern on when it crashes (ie, it crashes whenever a "42" is generated). 我建议输出所有生成的随机数,也许您会在崩溃时看到一个模式(即,只要生成“ 42”,它就会崩溃)。 Another option is to start adding a few log message in various functions (start with high level functions like your game update loop). 另一个选择是开始在各种功能中添加一些日志消息(从游戏更新循环之类的高级功能开始)。 After a crash check the log and begin adding more log messages until you narrow it down to one line/function. 崩溃后,请检查日志并开始添加更多日志消息,直到将其范围缩小到一行/函数为止。 This is not as quick as using the debugger can be but is sometimes a better choice, especially if you don't really know where to start looking. 这虽然没有使用调试器的速度快,但有时是更好的选择,尤其是在您真的不知道从哪里开始的时候。
  • Once you are able to reliably replicate the crash start removing things until the crash point changes or disappears. 一旦您能够可靠地复制崩溃,就开始删除内容,直到崩溃点更改或消失。 This may involve #ifdef s, commenting out code, setting application options, or even creating a temporary copy of the project so you can simply delete code, compile, and test. 这可能涉及#ifdef ,注释掉代码,设置应用程序选项甚至创建项目的临时副本,以便您可以简单地删除代码,编译和测试。 This may be difficult if the project is large/complex. 如果项目很大/很复杂,这可能很困难。
  • More information on the type of "crash" would be helpful. 有关“崩溃”类型的更多信息将很有帮助。 Usually programs don't just crash generically but have a certain exception occur, lock-up, etc.... Exception details can help you narrow down the source of the issue with some effort. 通常,程序不仅会崩溃,而且还会发生某些异常,锁定等。异常详细信息可以帮助您通过一些努力来缩小问题的根源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM