plshelp
plshelp

Reputation: 1

Pthread segment fault using pointer to variable in main

I'm new to pthread and attempting to implement a producer/consumer problem that will let the user pick buffer size, # of producers, # of consumers, and total # of items. I've been looking through what I thought were similar things on stack overflow, but can't seem to get it right.

My code has a main class and it spawns producers and consumers. It hands the producers and consumers a pointer to a stack initialized in main (or at least I'm trying to). I thought that what I was doing was legal and in CLion I get the predictive text options I want so I thought I linked it properly but I'm segfaulting when I try to read the top element.

I used GDB to make sure I knew what line I was crashing on, but don't understand what's wrong with my setup. While debugging I confirmed that a producer goes through its push() command first, but the consumer fails when attempting top() or pop(). I'd seen some threads here where the OP had problems because they didn't join their threads, but I am so I'm a little lost.

#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stack>
#include <cstring>
#include <semaphore.h>
#include <pthread.h>
#define N 10000

sem_t mutex;
sem_t fullCount;
sem_t emptyCount;
int iCount = 0;

typedef struct _thread_data{
    int id;
    int itemcount;
    std::stack<char>* ptr;
}thread_data;

void *producer(void *arg){
    std::cout << "spawned producer\n";
    thread_data *data = (thread_data *)arg;
    while(true){
        char message = 'X';
        sem_wait(&emptyCount);
        sem_wait(&mutex);
        if(iCount < data->itemcount){
            data->ptr->push(message);
            iCount++;
            char temp [25];
            sprintf(temp, "p:<%u>, item: %c, at %d\n", data->id, message, data->ptr->size());
            std::cout << temp;
            //std::cout << "hi I'm a producer\n";
            sem_post(&mutex);
            sem_post(&fullCount);
        }
        else{
            sem_post(&fullCount);
            sem_post(&mutex);
            pthread_exit(nullptr);
        }
    }
}

void *consumer(void *arg){
    std::cout << ("spawned consumer\n");
    thread_data *data = (thread_data *)arg;
    while(true){
        char message;
        sem_wait(&fullCount);
        sem_wait(&mutex);
        if(iCount < data->itemcount) {
            message = data->ptr->top(); //SEGFAULT
            char temp[25];
            printf(temp, "c:<%u>, item: %c, at %d\n", data->id, message, data->ptr->size());
            data->ptr->pop();
            std::cout << temp;
            //std::cout << "Hi I'm a consumer\n";
            sem_post(&mutex);
            sem_post(&emptyCount);
        }
        else if (iCount == data->itemcount){
            message = data->ptr->top(); //SEGFAULT
            char temp[25];
            printf(temp, "c:<%u>, item: %c, at %d\n", data->id, message, data->ptr->size());
            data->ptr->pop();
            std::cout << temp;
            sem_post(&emptyCount);
            sem_post(&mutex);
            pthread_exit(nullptr);
        }
        else{
            sem_post(&mutex);
            pthread_exit(nullptr);
        }

    }
}

int main(int argc, char *argv[]){
    int bufferSize = N;
    int pThreadCount,cThreadCount,itemCount;
    for (int x = 0; x < argc; ++x) {
        if(strcmp(argv[x],"-b") == 0){
            bufferSize = atoi(argv[x+1]);
        }
        if(strcmp(argv[x],"-p") == 0){
            pThreadCount = atoi(argv[x+1]);
        }
        if(strcmp(argv[x],"-c") == 0){
            cThreadCount = atoi(argv[x+1]);
        }
        if(strcmp(argv[x],"-i") == 0){
            itemCount = atoi(argv[x+1]);
        }
    }
    sem_init(&mutex,1,1);
    sem_init(&fullCount,1,0);
    sem_init(&emptyCount,1,bufferSize);

    std::stack<char> myStack;
    pthread_t myPThreads[pThreadCount];
    thread_data thrData[pThreadCount];
    pthread_t myCThreads[cThreadCount];
    thread_data cThrData[cThreadCount];

    for (int i = 0; i < pThreadCount; ++i) {
        thrData[i].id = i;
        thrData[i].itemcount = itemCount;
        thrData[i].ptr = &myStack;
        pthread_create(&myPThreads[i], NULL, producer, &thrData[i]);
    }
    for (int i = 0; i < cThreadCount; ++i) {
        cThrData[i].id = i;
        cThrData[i].itemcount = itemCount;
        thrData[i].ptr = &myStack;
        pthread_create(&myCThreads[i], NULL, consumer, &cThrData[i]);
    }

    for (int k = 0; k < pThreadCount; ++k) {
        pthread_join(myPThreads[k], NULL);
    }
    for (int j = 0; j < cThreadCount; ++j) {
        pthread_join(myCThreads[j], NULL);
    }

    return 0;
}

Upvotes: 0

Views: 60

Answers (2)

Igor Tandetnik
Igor Tandetnik

Reputation: 52471

cThrData[i].ptr is never initialized, for any i. consumer calls top() through an uninitialized pointer, whereupon the program exhibits undefined behavior.

Upvotes: 0

Igor Tandetnik
Igor Tandetnik

Reputation: 52471

iCount <= data->itemcount is always true. consumer never exits the loop. At some point, it exhausts the stack, and the subsequent top() call exhibits undefined behavior.

Upvotes: 1

Related Questions