Получение segfault с использованием С++ 11 std::thread

static T MultiplyElement(const Matrix& matrixA, const Matrix& matrixB, 
    unsigned M2col, unsigned M1row)
{
    T sumToReturn = 0;

    for (unsigned iM1colM2row = 0; iM1colM2row < matrixA.m_n; iM1colM2row++)
    {
        sumToReturn += 
            matrixA.m_data[M1row][iM1colM2row] * matrixB.m_data[iM1colM2row][M2col];
    }

    return sumToReturn;
}

...

    std::vector<std::thread> threads;
    for(unsigned i = 0; i < outM ; ++i)
    {
        for(unsigned j = 0; j < outN; ++j)
        {
            threads.push_back(std::thread([&]()
            {
                outMatrix.m_data[i][j] = MultiplyElement(matrixA, matrixB, i, j);
            }
            ));
        }
    }
    for(auto& thread : threads)
    {
        thread.join();
    }

Скомпилировано с помощью: clang++ -std=c++11 -stdlib=libc++ newFile.cpp

Я получаю segfault в MultiplyElement... есть идеи, почему?


person user2588666    schedule 23.01.2014    source источник
comment
Хорошо, вы прошлись по коду в отладчике и проверили строку кода, которая выдает ошибку? Может быть, неправильные индексы массива? Это не сайт человеческих отладчиков.   -  person OldProgrammer    schedule 24.01.2014
comment
Если вы удалите многопоточность, код выдаст правильный результат, так что этот тип отладки не то, что мне нужно. Ошибка является продуктом использования потоков, и я плохо разбираюсь в потоках С++ 11, поэтому я искал помощь сообщества :)   -  person user2588666    schedule 24.01.2014
comment
@user2588666 user2588666 Может условия гонки??   -  person πάντα ῥεῖ    schedule 24.01.2014
comment
Что касается условий гонки, я создал переменную для блокировки потока. И я пытался заблокировать до и разблокировать после вызова outMatrix.m_.... = Multi..., и я все еще получаю segfault.   -  person user2588666    schedule 24.01.2014
comment
Когда я уронил лямбду, она заработала... Наверное, в этом и была причина проблемы.   -  person user2588666    schedule 24.01.2014


Ответы (1)


Я думаю, что проблема в вашем захвате. Вы используете захват ссылок для всех переменных. Вы должны захватывать i и j по значению. Попробуйте [&, i, j] для пункта захвата.

Изменить: вы можете проверить ответ здесь. У вас такая же проблема.

person François Moisan    schedule 23.01.2014
comment
@CantChooseUsernames Они изменяются циклом. Но даже тогда они по-прежнему являются переменными локального масштаба. Если потоки запланированы после завершения одного или обоих циклов, вызов MultiplyElement будет выполнен с неопределенными значениями для M2Col и/или M1row. - person François Moisan; 24.01.2014
comment
И передача по значению изменит это как? Они все равно будут изменены циклом. Независимо от того, передает ли OP их по значению или по ссылке, здесь это не имеет никакого значения. Функции, принимающие переменные I и J, не изменяют его, и он получит то же значение, что и при передаче по значению. Кстати, MultiplyElement уже принимает I и J как передачу по значению. - person Brandon; 24.01.2014
comment
@CantChooseUsernames Неважно, принимает ли MultiplyElement их по значению или нет, потому что thread не будет вызывать эту функцию напрямую. Это будет сделано через лямбда-объект. Лямбда - это проблема, потому что она сохранит эти целые числа по ссылке. К тому времени, когда он будет вызван, эти целые числа могут быть давно утеряны, и мусор будет прочитан. - person François Moisan; 24.01.2014
comment
@Francois, к сожалению, я не могу это проверить, так как я отказался от исходного кода; однако я почти уверен, что это решило бы мою проблему. Определенно извлек уроки из этого. Спасибо! - person user2588666; 27.01.2014