0

I'm writing a program that need to using two mutex and 30+25 threads to run. However it made a segmentation fault. It successful complie, but fail to run. The segmentation fault is start in the beginning of the program (not the main) because I add a message after the first command in main, it doesn't print out.

But where is my program cause memory error before I start to enter the main part?

#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

using namespace std;
#define makingMachine   30
#define packingMachine  25

int *hotdog;
int total;
int pool = 0;
int packed = 0;
int **log;
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;

sem_t pack;
void* makeHotDog(void *arg)
{
    int id = *(int *)arg;
    int done = 0;
    long myMake = 0;
    while (!done) {
        pthread_mutex_lock(&mutex1);
        if (hotdog > 0) {
            sleep(rand()%3+4);
            hotdog--;
            myMake++;
            pool++;
            log[packed][0] = id;
            sleep(rand()%1+1);
            sem_post(&pack);
        }
        else {
            done = 1;
        }
        pthread_mutex_unlock(&mutex1);
    }

    pthread_exit((void *) myMake);
}

void* packHotDog(void *argc)
{
    int id = *(int *)argc;
    int done = 0;
    long myPack = 0;
    while (!done) {
        sem_wait(&pack);
        pthread_mutex_lock(&mutex2);
        if (packed <= total && pool > 0) {
            sleep(rand()%1+1);
            pool--;
            sleep(rand()%1+1);
            myPack++;
            log[packed][1] = id;
            sleep(rand()%1+1);
            packed++;
        }
        else {
            done = 1;
        }
        pthread_mutex_unlock(&mutex2);
    }

    pthread_exit((void *) myPack);
}

int main(int argc, char *argv[]) //master thread
{
    cin >> total;
    cout << "Success get number";
    hotdog = &total;
    log = new int*[total];
    for (int x = 0; x < total; x++)
        log[x] = new int[2];
    pthread_t maker[makingMachine], packer[packingMachine];
    int makerid[makingMachine], packerid[packingMachine];
    int i, rc;
    long total_make = 0, total_pack = 0;
    void *retval1, *retval2;
    cout<< "thread create";

    sem_init(&pack, 0, 0);

    cout << " sem ok " ;
    for (i = 0; i < makingMachine; i++) {
        makerid[i] = i;
        rc = pthread_create(&maker[i], NULL, makeHotDog, (void *)&makerid[i]);
        if (rc) {
            cout << "Error when creating threads!" << endl;
            exit(-1);
        }
    }

    for (i = 0; i < packingMachine; i++) {
        packerid[i] = i;
        rc = pthread_create(&packer[i], NULL, packHotDog, (void *)&packerid[i]);
        if (rc) {
            cout << "Error when creating threads!" << endl;
            exit(-1);
        }
    }

    for (i = 0; i < total; i++)
        cout << i+1 << log[i][0] << log[i][1];

    for (i = 0; i < makingMachine; i++) {
        rc = pthread_join(maker[i], &retval1);
        if (rc) {
            cout << "Error when joining threads!" << endl;
            exit(-1);
        }

        cout << "M, " << makerid[i]+1 << ", " << retval1 << endl;
        total_make += (long) retval1;
    }

    for (i = 0; i < packingMachine; i++) {
        rc = pthread_join(packer[i], &retval2);
        if (rc) {
            cout << "Error when joining threads!" << endl;
            exit(-1);           
        }

        cout << "P, " << packer[i] + 1 << ", " << retval2 << endl;
        total_pack += (long) retval2;
    }

    sem_destroy(&pack);
    pthread_exit(NULL);
}
Tom fong
  • 11
  • 2
  • 1
    Segmentation fault = Open in your debugger and find out why. Dumping that small mountain of code here with zero explanation is not helpful. – tadman Apr 02 '18 at 17:58
  • 4
    FWIW: C++11 introduced [``](http://en.cppreference.com/w/cpp/header/thread) which makes working with threads a lot easier and you don't have to sprinkle `void*`'s all over the place. – NathanOliver Apr 02 '18 at 17:58
  • 2
    You're using C++ so avoid doing `#define` and instead use `const` values. You've got a lot of ugly C habits to shake here. Using C++ conventions helps avoid a lot of mess. – tadman Apr 02 '18 at 17:58
  • @tadman why are `#define` bad thing in C++? –  Apr 02 '18 at 18:01
  • 3
    @GRC They are not needed in C++: https://stackoverflow.com/questions/6274008/why-would-someone-use-define-to-define-constants – NathanOliver Apr 02 '18 at 18:02
  • 2
    @GRC They're just dumb bits of text substituted into your code, not properly typed values, so the compiler doesn't know if you're putting a round peg in a square hole. When you misuse a `const` value you'll get an error and won't have to wonder why your code broke. – tadman Apr 02 '18 at 18:02
  • 1
    Given that code, the only reason I can see that it would segfault would be that the `PHREAD_MUTEX_INITIALIZER` macro fails. And the only reason I can see for that to fail, right off hand, is that your system does not support pthread. – fredrik Apr 02 '18 at 18:02
  • 2
    You are using cout without flushing the stream, add `cout << endl` and see when your program is aborted. Maybe problem is in `packHotDog` function where you are reading data out of range - in if condition `packed <= total` and you read `log[packed][1]` where first index can be only in range `[0,total-1]`. – rafix07 Apr 02 '18 at 18:31

0 Answers0