Question

Ok so I'm passing an argument to a thread that I use to tell it where to look in an array. I've got rid of the segmentation fault that was previously being thrown but it's still not working as I'd like. The int passed in pointer seems to change somewhere along the way. This throws the whole array out and I'm getting really random numbers in it. If there is any possible way anyone can help me sort this it'd be greatly appreciated. All I want the code to do is to read through a 2d array, select a random number (1, 2 or 5) to decide how many rows of the array will be processed by a thread and then create a number of threads to process the rows of the array. This could be the wrong way to go about it but I have no idea how else to do it. It's supposed to be class work to help me understand threads etc but so far I think it's just confusing me even more! Please help if you can!

int threadArray[10][10];
int arrayVar[10][2];

using namespace std;

void *calc(void *pointer){

  int *point, pointerA;
  point = (int *) pointer;
  pointerA = *point;

  int startPoint = arrayVar[pointerA][0];
  int endPoint = arrayVar[pointerA][1];

  int newArray[10][10];
  int calculated;

  for (int i = startPoint ; i < endPoint; i++){
    for (int j = 0; j < 10; j++){
      calculated = (threadArray[i][j] * 2 + 4) * 2 + 4;
      newArray[i][j] = calculated;
    }
  }

  for (int i = startPoint; i < endPoint; i++){
      for (int j = 0; j < 10; j++){
    cout << newArray[i][j] << " ";
      }
      cout << endl;
   }
  return 0;
}

int main(){
  int rc;
  int start = 0;
  int end;

  ifstream numFile;
  numFile.open("numbers.txt");

  if (numFile.is_open()){

    for (int row = 0; row < 10; row++){
      std::string line;
      std::getline(numFile, line);

      std::stringstream iss(line);

      for (int col = 0; col < 10; col++){
          std::string num;
      std::getline(iss, num, ' ');

          std::stringstream converter(num);
      converter >> threadArray[row][col];
      }

    }

    cout << "Original 2D Array" << endl << endl;
    for (int i = 0; i < 10; i++){
      for (int j = 0; j < 10; j++){
        cout << threadArray[i][j] << " ";
      }
      cout << endl;
    }

    cout << endl;
  }

    srand (time(NULL));

    const int rowArray[3] = {1, 2, 5};

    int arrayIndex = rand() % 3;
    int noOfRows = (rowArray[arrayIndex]);
    end = noOfRows;
    int noOfThreads = 10 / noOfRows;

    pthread_t threads[noOfThreads];

    arrayVar[noOfThreads][2];
    start = 0;
    end = noOfRows;

    for (int a = 0; a < noOfThreads; a++){
      arrayVar[a][0] = start;
      arrayVar[a][1] = end;
      start = start + noOfRows + 1;
      end = end + noOfRows + 1;
    }

    int *pointer = 0;

    cout << "2D Array Altered" << endl << endl;

    for (int t = 0; t < noOfThreads; t++){
      pointer = (int *) t;
      rc = pthread_create(&threads[t], NULL, calc, &pointer);
    }

    for (int t = 0; t < noOfThreads; t++){
      rc = pthread_join(threads[t], NULL);
    }
    pthread_exit(NULL);
}
Was it helpful?

Solution

Here's your problem:

for (int t = 0; t < noOfThreads; t++) {
  pointer = (int *) t;
  rc = pthread_create(&threads[t], NULL, calc, &pointer);
}

You are passing a pointer to pointer to pthread_create, and immediately destroying it when it goes out of scope at the end of the loop body. When the created thread starts running and dereferences that pointer, undefined behavior ensues.

You need to either eat some gray-area behavior and encode your integer in the void* argument to pthread_create:

void *calc(void *pointer) {
  int t = reinterpret_cast<int>(pointer);  
  // ...
}

// snip

for (int t = 0; t < noOfThreads; t++) {
  rc = pthread_create(&threads[t], NULL, calc, reinterpret_cast<void*>(t));
}

or dynamically allocate storage to pass an integer to the thread function.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top