简体   繁体   中英

c++ Multi-threading Argument Issues

I'm trying to pass a series of parameters into different c++ threads. The program runs fine when NumThreads == 1, however when NumThreads > 1, the p parameter I pass to the function is incorrect within the thread. Am I missing something in the thread constructor and not passing p by value?

Where the threads are created:

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

And the member function being called:

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

the console output from the first three threads: {

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

So ID and sample index are being passed correctly to the threads, but how is srcPoint the same for all three threads?!?

You are invoking undefined behavior by passing a pointer to a local variable to your threads and allowing the variable to go out of scope before it's used.

C-style arrays are never passed by value. A function declared to take an array type as an argument actually takes a pointer:

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

is equivalent to

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

In this case, your p array is local to your for loop scope, and it implicitly decays into a pointer to its first element when passed to your thread constructor. As soon as each iteration of your loop completes, p goes out of scope and is destroyed, but your thread still has a pointer to the memory it used to inhabit.

The best option to fix this would be to replace double p[3] with std::array<double, 3> p in your loop and to make MyClass::MyFunction take a parameter std::array<double, 3> srcPoint instead of double srcPoint[3] . Unlike raw C-style arrays, std::array can be passed by value, and implements the copy semantics you expect.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM