【问题标题】:Run-time error in program compiled with MinGW gcc/g++ (nuwen distro)使用 MinGW gcc/g++ (nuwen distro) 编译的程序中的运行时错误
【发布时间】:2019-05-31 06:16:27
【问题描述】:
#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;
}

这编译和运行 MSVC 没有问题。它使用gcc 编译没有错误,但mt19937 gen(rd()); 行导致程序崩溃并显示以下消息:

“myprog.exe 已停止工作

一个问题导致程序停止正常工作。如果有可用的解决方案,Windows 将关闭该程序并通知您。”

有什么想法吗?

gcc 命令:g++ mycode.cpp -fpermissive -s -o myprog.exe


更新: 在编译命令中添加-O2 可以让程序运行,尽管运行不正确。 “随机”函数不再是随机的;它总是返回 1。例如,使用以下“主”代码进行测试...

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;
}

...产生此输出:&lt;0, 1000&gt;

【问题讨论】:

  • 能否分享崩溃信息?
  • 我在 wandbox.org 中尝试了多个 GCC 版本——没有崩溃
  • @TheQuantumPhysicist myprog.exe 已停止工作 一个问题导致程序停止正常工作。如果有可用的解决方案,Windows 将关闭该程序并通知您。
  • 请注意,GCC 在 Windows 上一直存在 std::random_device 的问题 - 它可能总是产生相同的非随机数。您使用的是哪个 GCC 版本号?
  • 旁注:您可能不需要或不想在每次调用 randomBit 时重新设置随机数生成器的种子

标签: c++ gcc mingw


【解决方案1】:

这似乎是 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 不会提供随机数——它将是确定性的,总是给出相同的值。不幸的是标准允许它,在我看来这是一个大问题。

如果您每次运行只需要不同的值,请考虑使用其他非随机源作为种子,例如 C 库中的时间。如果您确实需要非确定性值,您可以使用 nuwen 发行版提供的 boost::random::random_device(与 std::random_device 相同的接口)。虽然它不是仅标题,因此您需要添加额外的链接:

g++ foo.cpp -lboost_random -lboost_system

【讨论】:

  • 我在使用 GCC 10.2.1 的 MCF-GCC 发行版时遇到了同样的崩溃。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-13
  • 1970-01-01
  • 1970-01-01
  • 2010-09-16
相关资源
最近更新 更多