c ++ прервало ядро, выгруженное во время pthread_join () - PullRequest
0 голосов
/ 02 октября 2019

Итак, я пытаюсь использовать многопоточность алгоритма Sieve of Eratosthenes, используя pthreads. Это мой код.

#include <iostream>
#include <iomanip>
#include <math.h>
#include <thread>
#include <string.h>
#include <chrono>
#include <vector>
#include <stdlib.h>
#include <pthread.h>

struct Thread_data {
  int thread_id;
  std::vector<int> prime_seed_vect;
  std::vector<int> chunk_vect;
};


void *calc_primes(void* td){
  Thread_data *td_t = (Thread_data *)td;
  std::vector<int> primes = td_t->prime_seed_vect;
  std::vector<int> chunk = td_t->chunk_vect;

  int chunk_start = chunk.front();
  int chunk_end = chunk.back();
  std::cout << "chunk_start: " << chunk_start << std::endl;
  std::cout << "chunk_end: " << chunk_end << std::endl;

  int k;
  int mult;
  int mark;

  for(std::vector<int>::size_type i=1; i!=primes.size(); i++){
    k = primes[i];

    mult = round(chunk_start/k);
    mark = k*mult;

    while(mark <= chunk_end){
      chunk[mark - chunk_start] = 0;
      mult += 1;
      mark = k*mult;
    } 
  }
  std::cout << "primes: " << k << std::endl;
  for(int i=0; i<(chunk_end-chunk_start); i++){
    if(chunk[i] != 0){
      std::cout << chunk[i] << " " << std::endl;
    }
  }
  std::cout << " done " << std::endl;
}

int main(int argc, char *argv[]){
  if(argc != 3){
    std::cout << "Run program on format \"./sieve max num_of_threads\"" << std::endl;
    return 0;
  }
  int num_threads = std::stoi(argv[2]);
  std::cout << "Threads: " << num_threads << std::endl;
  int max = std::stoi(argv[1]);
  std::cout << "max: " << max << std::endl;
  int sqrt_max = sqrt(max);
  std::cout << "sqrt_max: " << sqrt_max << std::endl;
  int chunk_size = (max-sqrt_max)/num_threads;
  std::cout << "chunk_size: " << chunk_size << std::endl;
  if(num_threads > (max-sqrt_max)){
    std::cout << "Not enough work for this amount of threads. exiting..." << std::endl;
    return 0;
  }
  std::vector<int> max_vect;
  std::vector<int> prime_seeds;

  for(int i=0; i<max; i++){
    max_vect.push_back(i+1);
  }
  std::cout << "max start: " << max_vect.front() << std::endl;
  std::cout << "max end: " << max_vect.back() << std::endl;

  int k = 2;
  int mult;
  int mark;

  //single thread part
  while(k*k <= sqrt_max){
    //set all multiples of k to 0 (mark them)
    mult = k;
    mark = k*mult;

    while(mark <= sqrt_max){
      max_vect[mark-1] = 0;
      mult += 1;
      mark = k*mult;
    }
    //find smallest unmarked number that is greater than k and set k to that number
    for(int i=k; i<=sqrt_max; i++){
      if(max_vect[i] != 0){
    k = max_vect[i];
    break;
      }
    }  
  }
  //put all unmarked numbers(primes) in a vector
  for(int i=0; i<=sqrt_max;i++){
    if(max_vect[i] != 0){
      prime_seeds.push_back(max_vect[i]);
    }
  }

  //multithread part
  pthread_t threads[num_threads];
  Thread_data td[num_threads];
  //give the seeds to all threads through a struct
  for(int i=0; i<num_threads; i++){
    int chunk_start = (i*chunk_size) + (sqrt_max + 1);
    int chunk_end;

    if(i == (num_threads-1)){
      chunk_end = chunk_start + chunk_size +((max - sqrt_max) % num_threads);
    }
    else{
      chunk_end = chunk_start + chunk_size;
    }

    td[i].thread_id = i;

    std::vector<int> temp1;
    for(int j=chunk_start; j<chunk_end; j++){
      temp1.push_back(j);
    }
    td[i].chunk_vect = temp1;
    td[i].prime_seed_vect = prime_seeds;

  }
  for(int i=0; i<num_threads; i++){
    pthread_create(&threads[i], NULL, calc_primes, &(td[i]));
  }
  std::cout << " After create " << std::endl;
  for(int i=0; i<num_threads; i++){
    std::cout << " inside join1 " << std::endl;
    pthread_join(threads[i], NULL);
    std::cout << " inside join2 " << std::endl;
  }
  std::cout << " After join " << std::endl;
  return 0;
}

Я компилирую с g++ -Wall -g -pthread -std=c++11 -o sieve.cpp, и когда я запускаю программу с ./sieve 35 1 (я ищу простые числа до 35 с 1 потоком), все работает нормально иЯ могу найти все простые числа и программа завершается правильно, но когда я запускаю ./sieve 36 1, я получаю эту ошибку:

free(): invalid pointer
Aborted (core dumped)

Кажется, что ошибка возникает в pthread_join, поэтому я, вероятно, ссылаюсь на некоторый объект, который не 'больше не существует? Проблема возникает при работе с более чем одним потоком. Я ценю все предложения и помощь!

...