2016-08-02 1 views
0

Я пытаюсь передать ряд параметров в разные потоки C++. Программа отлично работает, когда NumThreads == 1, однако, когда NumThreads> 1, параметр p, который я передаю функции, неверен в потоке. Я что-то пропустил в конструкторе потока и не передал значение p по значению?C++ Многопоточные проблемы аргумента

Где создаются темы:

int NumThreads = 2; 
std::thread t[numSamplePoints]; 
std::mutex dataLock; 

for(int i = 0 ; i < numSamplePoints ; i++) 
{ 
    // Prevent more than NumThreads from running at once 
    if(i > NumThreads && t[i-NumThreads].joinable()) 
    { 
    t[i - this->NumThreads].join(); 
    } 

    // Set and Check Input Parameters 
    double p[3]; 
    srcPoints->GetPoint(i , p); 
    if(i < 3) 
    { 
    cout<< "OUTTHREAD " << p[0] << " " << p[1] << " " << p[2] <<endl; 
    cout<< "src: " << Id << " index: " << i <<endl; 
    } 

    t[i] = std::thread(&MyClass::MyFunction, this, &dataLock, i, Id, p); 
} 

И функция-член вызывается:

void MyClass::MyFunction(std::mutex *dataLock, int sampleIndex, int Id, double srcPoint[3]) 
{ 
    dataLock->lock(); 
    if(sampleIndex < 3) 
    { 
    cout<< "IN THREAD " << srcPoint[0] << " " << srcPoint[1] << " " << srcPoint[2] <<endl; 
    cout<< "src: " << sourceId << " index: " << sampleIndex <<endl; 
    } 
    dataLock->unlock(); 
} 

консольный вывод из первых трех потоков: {

OUTTHREAD 45.7694 1.06209 -60.9628 
src: 0 index: 0 
OUTTHREAD 48.6044 -5.40514 -54.7663 
src: 108 index: 1 
OUTTHREAD 52.505 9.00298 -47.0499 
src: 216 index: 2 

IN THREAD 52.505 9.00298 -47.0499 
src: 0 index: 0 
IN THREAD 52.505 9.00298 -47.0499 
src: 108 index: 1 
IN THREAD 52.505 9.00298 -47.0499 
src: 216 index: 2 

Так Идентификатор идентификатора и индекс образца правильно передаются потокам, но как srcPoint то же самое для всех трех потоков?!?

+2

Вы передаете один и тот же массив 'p' в каждый поток, и вы можете изменить значения до того, как поток их прочитает. –

+0

@MattTimmermans Действительно ли 'p' - то же самое? Он выделяется заново на каждой итерации цикла for, или мне что-то не хватает? @JjBannister Мы не знаем, что такое 'srcPoints', и мы не знаем, что делает функция' GetPoints (int, double []) '. Возможно, это просто правильное поведение. – Mael

+0

Я согласен с @Mael, это может быть некорректное поведение в том, как вы его реализовали; который может быть _incorrect behavior_ в том, как вы ожидаете, что он будет действовать. Условия гонки такие забавные, как указывает Мэтт. – M4rc

ответ

1

Вы вызываете неопределенное поведение, передавая указатель на локальную переменную в свои потоки и позволяя переменной выйти из области действия до ее использования.

Маски C-стиля никогда не передаются по значению. Функция объявлена ​​взять тип массива в качестве аргумента действительно принимает указатель:

void MyClass::MyFunction(std::mutex *dataLock, int sampleIndex, int Id, double srcPoint[3]) 

эквивалентно

void MyClass::MyFunction(std::mutex *dataLock, int sampleIndex, int Id, double* srcPoint) 

В этом случае ваш p массив является локальным для вашей сферы for петли, и неявно распадается на указатель на свой первый элемент при передаче в ваш конструктор thread. Как только каждая итерация цикла завершается, p выходит за пределы области действия и уничтожается, но в вашем потоке по-прежнему есть указатель на память, в которой он использовался.

Самый лучший вариант, чтобы исправить это было бы заменить double p[3] с std::array<double, 3> p в цикле и сделать MyClass::MyFunction принимают параметр std::array<double, 3> srcPoint вместо double srcPoint[3]. В отличие от сырых массивов в стиле C, std::array может передаваться по значению и реализует семантику копирования, которую вы ожидаете.

+0

Так оно и было. Спасибо!! –

 Смежные вопросы

  • Нет связанных вопросов^_^