Ошибка времени выполнения в программе, скомпилированной с MinGW gcc / g ++ (nuwen distro) - PullRequest
0 голосов
/ 04 января 2019
#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


UPDATE: Добавление -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;
}

... выдает этот вывод: <0, 1000>

1 Ответ

0 голосов
/ 19 января 2019

Похоже, это проблема с дистрибутивом nuwen. Обе версии 16.0 и 16.1 генерируют некое неопределенное поведение в конструкторе std :: random_device или во время генерации значения, что иногда приводит к сбою в автоматическом режиме, но трудно создать минималистический пример.

Сбои, похоже, исчезают, когда код компилируется с уровнем оптимизации больше 0. Я бы не зависел от этого, так как, скорее всего, UB все еще где-то существует, и программа может аварийно завершить работу в самых неожиданных местах.

Версия 16.0 использует GCC 8.1.0, а 16.1 использует GCC 8.2.0. Я не мог воспроизвести эту ошибку с MinGW, загруженным с https://sourceforge.net/projects/mingw-w64/,, который также использует версию 8.1.0.

Кроме того, учтите, что std :: random_device в MinGW не будет предоставлять случайные числа - он будет детерминированным, всегда давая одинаковые значения. К сожалению, стандарт позволяет это делать, что, на мой взгляд, является большой проблемой.

Если вам просто нужны разные значения при каждом прогоне, рассмотрите возможность заполнения из других, не случайных источников, таких как время из библиотеки C. Если вам действительно нужны недетерминированные значения, вы можете использовать boost :: random :: random_device (тот же интерфейс, что и в std :: random_device), предоставляемый с дистрибутивом nuwen. Это не только заголовок, поэтому вам нужно добавить дополнительную ссылку:

g ++ foo.cpp -lboost_random -lboost_system

...