Deusgiggity Deusgiggity - 1 month ago 16
C++ Question

Semaphore array initializing to NULL, seg fault

I declared a semaphore array globally, as:

sem_t *exiting_on[11];


and attempt to initialize it in main, as:

for(int x = 0; x<11; x++)
sem_init(exiting_on[x], 0, 0);


Debugging has revealed something wrong in that completely normal (appearing) for loop, even though every example I've found while searching looks just like it. Maybe I'm missing something obvious, I'm not sure. I'll post the full code below, (simulates an elevator, similar to barbershop problem for semaphores) but I haven't managed to get it to run yet, so it is likely rife with other errors.

Any and all advice is welcome! This is all new for me, so I'm always looking to learn.

#include <pthread.h>
#include <iostream>
#include <stdlib.h>
#include <semaphore.h>

using namespace std;

sem_t lobby_people; //current number of people in the "lobby"
sem_t rider; //people on the elevator
sem_t ele_full; //tells the elevator it is full
sem_t arrived; //tells elevator the person got off, prevents closing the door before they leave
sem_t sim_done; //tells main that elevator is done
sem_t initialized; //tells main that person has recorded their pid from guest so that it can be safely incremented
sem_t *exiting_on[11]; //holds persons until they reach their desired floor
int pushed_button[11] = {0}; //craftily allows elevator to know how many people want to go to a floor
int current_floor = 1;
int target_floor =0;
int e_capacity = 7; //craftily allows people to know when to tell elevator to close

//Unimportant printing methods
//
//

void *person(void *pid)
{
int *person_number = static_cast<int*>(pid);
sem_post(&initialized);
target_floor = rand() % 9 + 2;
sem_wait(&rider);
board(*person_number, target_floor);
sem_wait(&lobby_people);
e_capacity--;
pushed_button[target_floor + 1]++;
if(e_capacity==0)
sem_post(&ele_full);
sem_wait(exiting_on[target_floor + 1]); //trying to use the array
get_off(*person_number);
sem_post(&arrived);
pthread_exit(NULL);
}

void *elevator(void *arg)
{
for(int trips = 0; trips < 7; trips++)
{
sem_wait(&ele_full);
close_door();
for(int current_floor = 1; current_floor < 11; current_floor++)
{
if(pushed_button[current_floor] != 0)
{
open_door(current_floor + 1);
while(pushed_button[current_floor] != 0)
{
sem_post(exiting_on[current_floor]); //also trying to use the array
sem_wait(&arrived);
}
close_door();
}
}
open_door(1);
e_capacity = 7;
for(int new_riders = 0; new_riders < 7; new_riders++)
sem_post(&rider);
}
sem_post(&sim_done);
pthread_exit(NULL);
}

int main()
{
//initializing our semaphores
sem_init(&lobby_people, 0, 0);
sem_init(&rider, 0, 7);
sem_init(&ele_full, 0, 0);
sem_init(&arrived, 0, 0);
sem_init(&sim_done, 0, 0);
sem_init(&initialized, 0, 0);

for(int x = 0; x<11; x++) //the likely culprit!
sem_init(exiting_on[x], 0, 0);

pthread_t my_thread;
pthread_create(&my_thread, NULL, &elevator, NULL); //starts elevator thread, which waits for riders

for(int guests = 0; guests < 49; guests++) //generates 49 people threads
{
sem_post(&lobby_people);
pthread_create(&my_thread, NULL, &person, &guests);
sem_wait(&initialized); //waits for the person to copy their value of guests before incrementing it
}
sem_wait(&sim_done); //awaits the end of the elevator's 7th run
complete();
return 0;
}

Answer
sem_t *exiting_on[11];

This declares an array of pointers to sem_t. The values in the array, the individuals pointers, are not initialized. The pointers are random junk.

sem_init() takes a valid pointer to a sem_t structure, and initializes it. Passing each uninitialized, invalid pointer, is undefined behavior. You should declare an array of sem_t structures themseves:

sem_t exiting_on[11];

And then initialize each one:

for(int x = 0; x<11; x++)
    sem_init(&exiting_on[x], 0, 0);