运行-使用 MinGW gcc/g++ (nuwen distro) 编译的程序中的时间错误
Run-time error in program compiled with MinGW gcc/g++ (nuwen distro)
#include <iostream>
#include <random>
using namespace std;
class myclass
{
private:
static bool randomBit()
{
std::random_device rd; // Obtain a random seed number from hardware
std::mt19937 gen(rd()); // Initialize and seed the generator <---- CRASH!!
uniform_int_distribution<> distr(0, 1); // Define the distribution range
return distr(gen);
}
myclass::myclass() = delete; // Disallow creating an instance of this object
public:
static bool generateRandomBit()
{
return randomBit();
}
};
int main()
{
cout<<myclass::generateRandomBit()<<endl;
return 0;
}
此编译和 运行s 使用 MSVC 没有问题。它使用 gcc
编译没有错误,但是 mt19937 gen(rd());
行导致程序崩溃并显示以下消息:
"myprog.exe 已停止工作
一个问题导致程序停止正常运行。 Windows 将关闭程序并在有可用解决方案时通知您。"
有什么想法吗?
gcc 命令:g++ mycode.cpp -fpermissive -s -o myprog.exe
更新:
将 -O2
添加到编译命令会使程序变为 运行,尽管这是不正确的。 "random" 函数不再随机;它总是 returns 1. 例如,使用以下 "main" 代码进行测试...
int main()
{
int a[2] {0, 0};
for (int i = 0; i < 1000; i++) {
a[myclass::generateRandomBit()]++;
}
cout<<"<"<<a[0]<<", "<<a[1]<<">"<<endl;
return 0;
}
...产生此输出:<0, 1000>
看来这是nuwen发行版的问题。
16.0 和 16.1 版本都会在 std::random_device 构造函数或值生成期间生成某种未定义的行为,有时会导致静默崩溃,但很难创建一个简约的示例。
当使用大于 0 的优化级别编译代码时,崩溃似乎消失了。
我不会依赖它,因为 UB 很可能仍然存在于某处,并且程序可能会在最意想不到的地方崩溃。
版本 16.0 使用 GCC 8.1.0,版本 16.1 使用 GCC 8.2.0。
我无法使用从 https://sourceforge.net/projects/mingw-w64/ 下载的 MinGW 重现此错误,它也使用 8.1.0 版本。
此外,请注意 MinGW 上的 std::random_device 不会提供随机数 - 它是确定性的,始终提供相同的值。不幸的是标准允许它,我认为这是一个大问题。
如果您只需要每个 运行 的不同值,请考虑使用其他 not-random 来源播种,例如来自 C 库的时间。如果你真的需要 non-deterministic 值,你可以使用 boost::random::random_device(与 std::random_device 相同的界面),与 nuwen 发行版一起提供。它不是 header-only,所以你需要添加额外的链接:
g++ foo.cpp -lboost_random -lboost_system
#include <iostream>
#include <random>
using namespace std;
class myclass
{
private:
static bool randomBit()
{
std::random_device rd; // Obtain a random seed number from hardware
std::mt19937 gen(rd()); // Initialize and seed the generator <---- CRASH!!
uniform_int_distribution<> distr(0, 1); // Define the distribution range
return distr(gen);
}
myclass::myclass() = delete; // Disallow creating an instance of this object
public:
static bool generateRandomBit()
{
return randomBit();
}
};
int main()
{
cout<<myclass::generateRandomBit()<<endl;
return 0;
}
此编译和 运行s 使用 MSVC 没有问题。它使用 gcc
编译没有错误,但是 mt19937 gen(rd());
行导致程序崩溃并显示以下消息:
"myprog.exe 已停止工作
一个问题导致程序停止正常运行。 Windows 将关闭程序并在有可用解决方案时通知您。"
有什么想法吗?
gcc 命令:g++ mycode.cpp -fpermissive -s -o myprog.exe
更新:
将 -O2
添加到编译命令会使程序变为 运行,尽管这是不正确的。 "random" 函数不再随机;它总是 returns 1. 例如,使用以下 "main" 代码进行测试...
int main()
{
int a[2] {0, 0};
for (int i = 0; i < 1000; i++) {
a[myclass::generateRandomBit()]++;
}
cout<<"<"<<a[0]<<", "<<a[1]<<">"<<endl;
return 0;
}
...产生此输出:<0, 1000>
看来这是nuwen发行版的问题。 16.0 和 16.1 版本都会在 std::random_device 构造函数或值生成期间生成某种未定义的行为,有时会导致静默崩溃,但很难创建一个简约的示例。
当使用大于 0 的优化级别编译代码时,崩溃似乎消失了。 我不会依赖它,因为 UB 很可能仍然存在于某处,并且程序可能会在最意想不到的地方崩溃。
版本 16.0 使用 GCC 8.1.0,版本 16.1 使用 GCC 8.2.0。 我无法使用从 https://sourceforge.net/projects/mingw-w64/ 下载的 MinGW 重现此错误,它也使用 8.1.0 版本。
此外,请注意 MinGW 上的 std::random_device 不会提供随机数 - 它是确定性的,始终提供相同的值。不幸的是标准允许它,我认为这是一个大问题。
如果您只需要每个 运行 的不同值,请考虑使用其他 not-random 来源播种,例如来自 C 库的时间。如果你真的需要 non-deterministic 值,你可以使用 boost::random::random_device(与 std::random_device 相同的界面),与 nuwen 发行版一起提供。它不是 header-only,所以你需要添加额外的链接:
g++ foo.cpp -lboost_random -lboost_system