C ++ srand,rand中的一个DLL奇怪的行为

时间:2012-06-10 04:26:58

标签: c++ dll random srand

我正在主持人工智能竞赛,并有一个随机选择随机可能的值。

机器人有2个导出函数:Init(_seed)和MakeMove()

要播放完全相同的游戏主机,每个机器人都有一个已定义的种子值。并将其传递给Init函数。

随机bot的Init函数有一个srand(_seed)函数调用。 随机机器人的MakeMove函数有一个rand()函数调用。

现在的问题是,在加载2个机器人之后,每个游戏应该使用相同的种子值相同,但它们是不同的。

我知道srand应该存储每个模块/线程的值,而不是共享它。

我做了一个测试并创建了一个函数mysrand和myrand,它们不会分别通过调用srand和rand导出。

我用mysrand和myrand替换了导出函数中的srand和rand ......并且它工作了......

我知道为什么会这样,但不确定......

那么为什么会发生这种情况以及如何避免它因为我希望参赛者在导出的函数中使用他们想要的任何函数(不想使用我的代理函数)。

感谢。

我正在使用windows,编译器:gcc,visual C ++,borland C ++ builder

3 个答案:

答案 0 :(得分:5)

如果您想获得一致的行为,<random>库可能是更好的选择。您可以控制存储RNG状态的位置,并且引擎可以跨实现生成相同的值(尽管不需要标准分布在实现中生成相同的输出)。

#include <random>
#include <iterator>
#include <algorithm>
#include <iostream>

int main() {
    std::mt19937 eng;
    std::generate_n(std::ostream_iterator<int>(std::cout, " "), 10, [&] {
        // A simple example distribution function; not intended for real use.
        return static_cast<int>(eng()/static_cast<double>(eng.max() + 1ull) * 20.0) + 1;
    });
}

这应该在所有实现上输出以下内容:

  

17 3 19 17 3 20 19 5 13 7

如果您只需要实现中的一致行为而不是跨实现,那么您可以使用标准分布,并且您仍然可以控制RNG的状态。

#include <random>
#include <iterator>
#include <algorithm>
#include <iostream>

int main() {
    std::mt19937 eng;
    std::uniform_int_distribution<> dist(1,20);
    std::generate_n(std::ostream_iterator<int>(std::cout, " "), 10, [&] { return dist(eng); });
}

标准发行版应优先于编写自己的发行版。

答案 1 :(得分:1)

  

我知道srand应该存储每个模块/线程的值,而不是共享它。

这不一定是真的。来自Ubuntu上的rand手册页:

 The function rand() is not reentrant or thread-safe, since it uses hid‐
   den state that is modified on each call.  This might just be  the  seed
   value to be used by the next call, or it might be something more elabo‐
   rate.  In order to get reproducible behavior in a threaded application,
   this  state must be made explicit; this can be done using the reentrant
   function rand_r().

如果您的C库实现没有明确使用本地状态而不是rand的共享状态,则最终可能会破坏RNG状态。

答案 2 :(得分:1)

您可以将每个dll静态链接到CRT,它会为每个dll提供自己的rand状态。