pthread_cond_wait in "produce_numbers" gives me segmentation fault - c

My problem is that I can't initialize the circular_buffer in main() and the basic problem is that when the program calls pthread_cond_wait() in the produce_numbers() function, I take a segmentation fault.
My code is below.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int seed;
typedef struct circular_buffer {
void *buffer; // data buffer
void *buffer_end; // end of data buffer
size_t capacity; // maximum number of items in the buffer
size_t count; // number of items in the buffer
size_t sz; // size of each item in the buffer
void *head; // pointer to head
void *tail; // pointer to tail
pthread_mutex_t mutex; // needed to add/remove data from the buffer
pthread_cond_t can_produce; // signaled when items are removed
pthread_cond_t can_consume; // signaled when items are added
} circular_buffer;
struct thread_data {
int thread_id;
int thread_id2;
int seed;
int numbersofprod;
int talenum;
};
struct thread_data thread_data_array[40];
void cb_init(circular_buffer *cb, size_t capacity, size_t sz)
{
cb->buffer = malloc(capacity * sz);
if (cb->buffer == NULL) {
printf("Could not allocate memory..Exiting! \n");
exit(1);
}
// handle error
cb->buffer_end = (char *)cb->buffer + capacity * sz;
cb->capacity = capacity;
cb->count = 0;
cb->sz = sz;
cb->head = cb->buffer;
cb->tail = cb->buffer;
}
// remove first item from circular item void
cb_pop_front(circular_buffer *cb, void *item)
{
printf("pop_front");
if (cb->count == 0) {
printf("Access violation. Buffer is empty\n");
exit(1);
}
memcpy(item, cb->tail, cb->sz);
cb->tail = (char *)cb->tail + cb->sz;
if (cb->tail == cb->buffer_end)
cb->tail = cb->buffer;
cb->count--;
}
// add item to circular buffer
void cb_push_back(circular_buffer *cb, const void *item)
{
if (cb->count == cb->capacity) {
printf("Access violation. Buffer is full\n");
exit(1);
}
memcpy(cb->head, item, cb->sz);
cb->head = (char *)cb->head + cb->sz;
if (cb->head == cb->buffer_end)
cb->head = cb->buffer;
cb->count++;
}
// destroy circular buffer
void cb_free(circular_buffer *cb)
{
free(cb->buffer);
// clear out other fields too, just to be safe
}
void *consume_numbers(void *arg)
{
struct thread_data *my_data;
int threadId = my_data->thread_id2;
int rc;
circular_buffer *cb =
(circular_buffer *)arg; // δήλωση δείκτη σε δομή circular_buffer
printf("to capacity einai %d!\n", cb->capacity);
while (1) {
pthread_mutex_lock(&cb->mutex);
// elegxos an to buffer einai adeio
if (cb->count == 0) { // empty
// wait for new items to be appended to the buffer
printf("eeeeeee");
pthread_cond_wait(&cb->can_consume, &cb->mutex);
} // if
int *tmp_read = (int *)malloc(4);
cb_pop_front(cb, (void *)tmp_read);
free(tmp_read);
printf("Thread: consuming item %d!\n", cb->count);
// signal the fact that new items may be produced
rc = pthread_cond_signal(&cb->can_produce);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_signal() is %d\n", rc);
pthread_exit(&rc);
} // if
rc = pthread_mutex_unlock(&cb->mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_unlock() is %d\n", rc);
pthread_exit(&rc);
} // if
} // while
// de ftanei pote edw
return NULL;
} // consume_numbers
void *produce_numbers(void *threadarg)
{
struct thread_data *my_data;
my_data = (struct thread_data *)threadarg;
int seeed = my_data->seed;
int numberofprod = my_data->numbersofprod;
int threadId = my_data->thread_id;
int talenumber = my_data->talenum;
int j, r;
int *tid;
int rc;
circular_buffer *cb;
// open file
FILE *f = fopen("producers_in.txt", "w");
if (f == NULL) {
printf("Error opening file!\n");
exit(1);
} // telos anoigmatos arxeiou
srand(seeed); // paragwgi sporou
for (j = 0; j < numberofprod; j++) {
pthread_mutex_lock(&cb->mutex);
// elegxos an o buffer einai full
if (cb->count == cb->capacity) {
// wait until some elements are consumed
printf("mpika");
// pthread_cond_wait(&cb->can_produce, &cb->mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_wait() is %d\n",
rc);
pthread_exit(&rc);
} // if
} // while
else {
r = rand();
printf("tyxaios arithmos %d\n", r);
cb_push_back(
cb, (void *)&r); // grapse sto arxeio txt ton tyxaio arithmo r
const char *text = "the random number of producer with id";
fprintf(f, "%s ", text);
tid = (int *)threadarg;
fprintf(f, "%d\n", tid);
const char *text2 = "is";
fprintf(f, " %s ", text2);
fprintf(f, "%d\n", r);
printf("to count einai %d\n", cb->count);
// signal the fact that new items may be consumed
rc = pthread_cond_signal(&cb->can_consume);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_signal() is %d\n",
rc);
pthread_exit(&rc);
} // if
rc = pthread_mutex_unlock(&cb->mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_unlock() is %d\n",
rc);
pthread_exit(&rc);
} // if
} // else
} // for
fclose(f);
// NEVER REACHED
tid = (int *)threadarg;
pthread_exit(tid);
} // produce_numbers
// MAIN
int main(int argc, char *argv[])
{
if (argc != 6) {
printf("ERROR: the program should take 5 argument!\n");
exit(-1);
}
int producers = atoi(argv[1]);
int consumers = atoi(argv[2]);
int numbersofprod = atoi(argv[3]);
int talenum = atoi(argv[4]);
int seed = atoi(argv[5]);
/*elegxoume oti ta dedomena pou dothikan einai swsta.*/
if (producers < 1) {
printf("ERROR: the number of producers to run should be a positive number.Current number given %d.\n",
producers);
exit(-1);
}
if (consumers < 1) {
printf(
"ERROR: the number of consumers to run should be a positive number.Current number given %d.\n", consumers);
exit(-1);
}
if (numbersofprod <
1) {
printf("ERROR: the number of numbersofprod to run should be a positive number. Current number given %d.\n", numbersofprod);
exit(-1);
}
if (talenum < 1) {
printf("ERROR: the number of tale to run should be a positive number. Current number given %d.\n", talenum);
exit(-1);
}
if (seed < 1) {
printf("ERROR: the number of the seed to run should be a positive number. Current number given %d.\n", seed);
exit(-1);
}
printf("Main: We will create %d producer threads", producers);
printf(" and %d consumers threads.\n", consumers);
pthread_t *prod;
pthread_t *cons;
prod = malloc(producers * sizeof(pthread_t));
if (prod == NULL) {
printf("NOT ENOUGH MEMORY!\n");
return -1;
}
cons = malloc(consumers * sizeof(pthread_t));
if (cons == NULL) {
printf("NOT ENOUGH MEMORY!\n");
return -1;
}
int rc;
int rc2;
int threadCount;
int threadCount2;
int countArray[producers];
int countArray2[consumers];
//INITIALIZE MUTEX AND CONDITION VARIABLES
circular_buffer cb = {
.count=0,
.mutex = PTHREAD_MUTEX_INITIALIZER,
.can_produce = PTHREAD_COND_INITIALIZER,
.can_consume = PTHREAD_COND_INITIALIZER
};
cb_init(cb, talenum, 1); //end_of initializing
for (threadCount = 0; threadCount < producers; threadCount++) {
printf("Main: creating thread %d for producers\n ",
threadCount);
countArray[threadCount] = threadCount + 1;
thread_data_array[threadCount].thread_id = threadCount;
thread_data_array[threadCount].talenum = talenum;
thread_data_array[threadCount].seed = seed;
thread_data_array[threadCount].numbersofprod =
numbersofprod; /*dimiourgia tou thread*/
rc = pthread_create(&prod[threadCount], NULL, produce_numbers,
(void *)&thread_data_array[threadCount]);
/*elegxos oti to thread dimiourgithike swsta.*/
if (rc != 0) {
printf("ERROR: return code from pthread_create() is %d\n",
rc);
exit(-1);
}
for (threadCount2 = 0; threadCount2 < consumers;
threadCount2++) {
countArray2[threadCount2] = threadCount2 + 1;
thread_data_array[threadCount2].thread_id2 = threadCount2;
printf("Main: creating thread %d for consumers\n",
threadCount);
/*dimiourgia tou thread*/
rc2 = pthread_create(cons, NULL, consume_numbers,
(void *)&cb);
/*elegxos oti to thread dimiourgithike swsta.*/
if (rc2 != 0) {
printf(
"ERROR: return code from pthread_create() is %d\n",
rc2);
exit(-1);
}
}
}
void *status;
for (threadCount = 0; threadCount < producers;
threadCount++) {
rc = pthread_join(prod[threadCount], &status);
if (rc != 0) {
printf("ERROR: return code from pthread_join() is %d\n",
rc);
exit(-1);
}
printf("Main: Thread %d returned %d as status code.\n",
countArray[threadCount], (*(int *)status));
}
free(prod);
`` return 1;
void *status2;
for (threadCount2 = 0; threadCount2 < consumers; threadCount2++) {
rc2 = pthread_join(cons[threadCount2], &status2);
if (rc2 != 0) {
printf("ERROR: return code from pthread_join() is %d\n",
rc);
exit(-1);
}
printf("Main: Thread % d returned % d as status code.\n ", countArray2[threadCount2],
(*(int *)status2));
}
free(cons);
return 1;
}

Your problem is that you never call pthread_cond_init() on the cb.can_produce and cb.can_consume condition variables that are members of the struct circular_buffer.
You need to change the cb_init() function so that it initialises the new circular_buffer's mutex, can_produce and can_consume members with pthread_mutex_init() and pthread_cond_init().
You are also using the pointer variable cb uninitialised in the produce_numbers() function - it's declared as struct circular_buffer *cb; but never assigned to. You need to make cb a member of struct thread_arg instead, and set it in main() so that produce_numbers() has a reference to the same struct circular_buffer object as the other threads.

Related

pthread program crashes while I fetch buffer size in C

I'm trying to build a lift simulator in which a thread adds lift requests to the buffer and three threads representing lifts take the requests from the buffer and stimulate them simultaneously. I'm using pthread.h and semaphore.h to help me with the multithreaded nature of the program. As the requests need to be served in the order they are produced, I thought it would be best to use a queue as the buffer.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <semaphore.h>
#define THREAD_NUM 4
sem_t semEmpty;
sem_t semFull;
pthread_mutex_t mutexBuffer;
pthread_cond_t cond;
pthread_cond_t condII;
// file pointer assignment statements.
FILE *input;
FILE *output;
int count = 0;
int totalRequests = 0;
int totalMovement = 0;
// A structure to store requests.
struct Request
{
int reqNo;
int from;
int to;
};
// A structure to store lift info.
struct Lift
{
int liftNo;
int c_pos;
int movement;
int tMovement;
int tRequests;
};
// Declaring and defining queue functions.
struct queue
{
int size;
int f;
int r;
struct Request *arr;
};
int isEmpty(struct queue *q)
{
if (q->r == q->f)
{
return 1;
}
return 0;
};
int isFull(struct queue *q)
{
if (q->r == q->size - 1)
{
return 1;
}
return 0;
};
void enqueue(struct queue *q, struct Request req)
{
if (isFull(q))
{
printf("This Queue is full\n");
}
else
{
q->r++;
q->arr[q->r] = req;
printf("Enqued element.\n");
}
};
struct Request dequeue(struct queue *q)
{
struct Request r;
if (isEmpty(q))
{
printf("This Queue is empty.\n");
}
else
{
q->f++;
r = q->arr[q->f];
printf("Dequed element.\n");
}
return r;
};
// Declaring Buffer.
struct queue Buffer;
void *request(void *args)
{
struct Request r1;
while (!feof(input))
{
fscanf(input, "%d %d %d", &r1.reqNo, &r1.from, &r1.to);
fprintf(output, "--------------------------------------------\n");
fprintf(output, "Request No: %d\n", r1.reqNo);
fprintf(output, "From Floor %d to Floor %d\n", r1.from, r1.to);
fprintf(output, "--------------------------------------------\n");
while (isFull(&Buffer) == 1)
{
pthread_cond_wait(&condII, NULL);
}
sem_wait(&semEmpty);
pthread_mutex_lock(&mutexBuffer);
enqueue(&Buffer, r1);
count++;
pthread_mutex_unlock(&mutexBuffer);
sem_post(&semFull);
}
}
void *lift(void *args)
{
pthread_mutex_lock(&mutexBuffer);
struct Lift currentLift = *(struct Lift *)args;
struct Request r1;
pthread_mutex_unlock(&mutexBuffer);
while (count > 0)
{
while(isEmpty(&Buffer) == 0){
sem_wait(&semFull);
pthread_mutex_lock(&mutexBuffer);
r1 = dequeue(&Buffer);
count--;
pthread_cond_broadcast(&condII);
currentLift.movement = 0; // Resetting movement.
currentLift.tRequests++; // Incrementing total requests for lift.
totalRequests++; // Incrementing total requests.
fprintf(output, "Lift %d Operations\nPrevious Position: %d Floor\nRequest: number %d from Floor %d to Floor %d\n", currentLift.liftNo, currentLift.c_pos, r1.reqNo, r1.from, r1.to);
fprintf(output, "Detail Operations:\n\tGo from Floor %d to Floor %d\n", currentLift.c_pos, r1.from);
// Stimulating lift movement.
sleep(1);
currentLift.movement += abs(currentLift.c_pos - r1.from);
currentLift.c_pos = r1.from;
fprintf(output, "\tGo from Floor %d to Floor %d\n", r1.from, r1.to);
sleep(1);
currentLift.movement += abs(r1.to - r1.from);
currentLift.c_pos = r1.to;
currentLift.tMovement += currentLift.movement; // Adding to total movement of lift.
fprintf(output, "\t#movement for this request: %d\n", currentLift.movement);
fprintf(output, "\t#Requests: %d\n", currentLift.tRequests);
fprintf(output, "\tTotal #movement: %d\n", currentLift.tMovement);
fprintf(output, "Current Position: %d Floor\n", r1.to);
pthread_mutex_unlock(&mutexBuffer);
sem_post(&semEmpty);
pthread_mutex_lock(&mutexBuffer);
totalMovement += currentLift.tMovement;
pthread_mutex_unlock(&mutexBuffer);
}
}
}
int main(int argc, char *argv[])
{
// Creating thread array, mutexes, semaphores, and lifts.
pthread_t threads[THREAD_NUM];
pthread_mutex_init(&mutexBuffer, NULL);
sem_init(&semEmpty, 0, 5);
sem_init(&semFull, 0, 0);
pthread_cond_init(&cond, NULL);
pthread_cond_init(&condII, NULL);
Buffer.size = 5;
Buffer.f = -1;
Buffer.r = -1;
Buffer.arr = malloc(sizeof(struct Request) * Buffer.size);
struct Lift l1, l2, l3;
// Setting values for lifts.
l1.liftNo = 1;
l2.liftNo = 2;
l3.liftNo = 3;
l1.c_pos = 1;
l2.c_pos = 1;
l3.c_pos = 1;
l1.tMovement = 0;
l2.tMovement = 0;
l3.tMovement = 0;
l1.tRequests = 0;
l2.tRequests = 0;
l3.tRequests = 0;
l1.movement = 0;
l2.movement = 0;
l3.movement = 0;
// Dynamically allocating lifts for use in threads.
struct Lift *lift1 = malloc(sizeof(struct Lift));
*lift1 = l1;
struct Lift *lift2 = malloc(sizeof(struct Lift));
*lift2 = l3;
struct Lift *lift3 = malloc(sizeof(struct Lift));
*lift3 = l2;
// assigning files to file pointers.
input = fopen("sim_input.txt", "r");
if (input == NULL)
{
printf("No file read.\n\n");
return -1;
}
else
{
fseek(input, 0, SEEK_SET);
printf("File read successfully.\n\n");
}
output = fopen("sim_out.txt", "w");
if (output == NULL)
{
printf("No file read.\n\n");
return -1;
}
else
{
printf("File read successfully.\n\n");
}
// Creating producer thread and joining.
if (pthread_create(&threads[0], NULL, &request, NULL) != 0)
{
perror("Failed to create thread");
}
if (pthread_join(threads[0], NULL) != 0)
{
perror("Failed to join thread");
}
// Creating threads and passing lift structures.
if (pthread_create(&threads[1], NULL, &lift, lift1) != 0)
{
perror("Failed to create thread");
}
if (pthread_create(&threads[2], NULL, &lift, lift2) != 0)
{
perror("Failed to create thread");
}
if (pthread_create(&threads[3], NULL, &lift, lift3) != 0)
{
perror("Failed to create thread");
}
// Joining all lifts using loop structure.
for (int i = 1; i < THREAD_NUM; i++)
{
if (pthread_join(threads[i], NULL) != 0)
{
perror("Failed to join thread");
}
}
// Printing total requests and total movements.
fprintf(output, "Total number of requests: %d\n", totalRequests);
fprintf(output, "Total number of movements: %d\n", totalMovement);
// Freeing memory.
if (count < 1)
{
sem_destroy(&semEmpty);
sem_destroy(&semFull);
pthread_cond_destroy(&cond);
pthread_cond_destroy(&condII);
pthread_mutex_destroy(&mutexBuffer);
fclose(input);
fclose(output);
free(lift1);
free(lift2);
free(lift3);
}
return 0;
}
Here's the complete code for the program. It requires sim_input.txt with the following contents:
1 1 5
2 7 2
3 3 8
4 4 11
5 12 15
6 2 9
7 11 7
8 8 15
9 12 19
10 20 7
I assume the program crashes at while(isEmpty(&Buffer) == 0) where I try to fetch the size of the Buffer(Queue) but there might be some other reason too, can you please help?
I assume the program crashes at
You shouldn't assume. Run your program under debugger and observe where it crashes.
Your question lacks MCVE, because your program requires input file sim_input.txt which you didn't provide.
There are obvious bugs though -- you are accessing Buffer from multiple threads, some but not all of these accesses are guarded by a mutex.
For a mutex to be effective, all accesses to variables shared between multiple threads must be guarded, or you will have a data race, which is undefined behavior.
Update:
The actual crash is happening here:
pthread_cond_wait(&condII, NULL);
This call makes absolutely no sense: you must provide a mutex to pthread_cond_wait, and it must be the same mutex as the one used in pthread_cond_signal or similar. Here it should be mutexBuffer, and the code should look something like:
pthread_mutex_lock(&mutexBuffer);
while (isFull(&Buffer)) {
pthread_cond_wait(&condII, &mutexBuffer);
}
// sem_wait() <<- this is bogus/unnecessary
enqueue(&Buffer, r1);
count++;
pthread_mutex_unlock(&mutexBuffer);
There are many other bugs as well, e.g. the code in lift() assumes that it will run after request has been enqueued, and will exit immediately if that hasn't happened.
In my runs, all 3 lift threads exit before a single request is processed.

C program: Parent read one file and child count the number of words. Child have 4 Threads and mapper and reducer is also used

I am writing a C program in which I have a child and a parent. Parent and child share data using shared memory. What I am doing is asking parent to write the file in shared memory and child process then reads the file from shared memory and outputs a list showing the count of each unique word.
What I have to do is use 4 thread in child program and also use mapper and reducer to accomplish the task.
The text file is having around 30000 lines in it. My program is running correctly if I pass only 20000 lines in the text file but, now running for the whole file.
Please If someone can have a look at my program and let me know where I am going wrong will be surely appreciated.
Here is the link to the text file: http://cis-linux1.temple.edu/~qzeng/cis5512-fall2016/papers/ANNA_KARENINA.txt
And here is the code I am trying to run:
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <ctype.h>
#define NUM_THREADS 4
static key_t key = (key_t) 0;
static int size = 0;
struct thread_data
{
int thread_id;
char *msg;
char* wordary[10000][2];
int size;
};
struct thread_data thread_data_array[NUM_THREADS];
void *CountWords(void *threadarg)
{
int taskid, j, i=0, flag=0, index = 0, p, k,z, cnt, m;
char *msg_words, c, *word, buffer[8];
char* word_array[10000][2];
struct thread_data *my_data;
my_data = (struct thread_data *) threadarg;
taskid = my_data->thread_id;
msg_words = my_data->msg;
strcat(msg_words," ");
word = (char*) malloc(20);
word_array[0][0] = (char*) malloc(30);
word_array[0][1] = (char*) malloc(8);
FILE *out;
if(taskid==0)
out=fopen("out.txt","w");
//printf("%d\n", strlen(msg_words));
for(j=0; j < strlen(msg_words); j++)
{
c = msg_words[j];
c = tolower(c);
if(c == '\n')
{
c = ' ';
}
if(!isspace(c))
{
word[i++] = c;
}
if(c == '\0')
{
break;
}
if(c == ' ')
{
flag = 0;
for(k=0; k <= index; k++)
{
if(0 == strcmp(word_array[k][0],word))
{
flag = 1;
cnt = atoi(word_array[k][1]);
cnt++;
sprintf(buffer, "%d", cnt);
strcpy(word_array[k][1],buffer);
}
}
if(flag == 0)
{
strcpy(word_array[index][0],word);
strcpy(word_array[index][1],"1");
index++;
word_array[index][0]=(char*)malloc(30);
word_array[index][1]=(char*)malloc(8);
}
for(p=0; p <= 20; p++)
{
word[p] = 0;
}
i = 0;
//printf("%d",index);
}
//my_data->size = index;
}
printf("%d\n",index);
my_data->size = index;
for(m = 0; m<index; m++)
{
//printf("%d",m);
my_data->wordary[m][0] = (char*) malloc(30);
my_data->wordary[m][1] = (char*) malloc(8);
strcpy(my_data->wordary[m][0], word_array[m][0]);
strcpy(my_data->wordary[m][1], word_array[m][1]);
//printf("%s %s\n", my_data->wordary[m][0], my_data->wordary[m][1]);
}
pthread_exit((void *)my_data);
}
void main()
{
int ShmID, index = 0;
char* ShmPTR;
pid_t pid;
int status;
clock_t begin, end;
double time_spent;
begin = clock();
FILE *txtfile, *out_file;
txtfile = fopen("test.txt", "r");
fseek(txtfile, 0, SEEK_END); // seek to end of file
size = ftell(txtfile); // get current file pointer
fseek(txtfile, 0, SEEK_SET);
//printf("size : %d", size);
key = ftok(__FILE__,'x');
ShmID = shmget(key, size, IPC_CREAT | 0666);
if (ShmID < 0) {
printf("*** shmget error (server) ***\n");
exit(1);
}
printf("Server has received a shared memory\n");
ShmPTR = (char *) shmat(ShmID, NULL, 0);
if (ShmPTR == (char *)(-1)) {
printf("*** shmat error (server) ***\n");
exit(1);
}
printf("Server has attached the shared memory...\n");
while(!feof(txtfile))
{
ShmPTR[index] = fgetc(txtfile);
index++;
}
//ShmPTR[index] = '\0';
printf("Server is about to fork a child process...\n");
pid = fork();
if (pid < 0)
{
printf("*** fork error (server) ***\n");
exit(1);
}
else if (pid == 0)
{
printf(" Client process started\n");
//printf("%s",shm);
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
int rc, t, shmsz1, shmsz2, shmsz3;
char* split_ShmPTR[4];
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
//printf("1111");
//printf("%d\n",size);
shmsz1 = (int)(size/4);
shmsz2 = shmsz1*2;
shmsz3 = shmsz1*3;
// printf("%d %d %d\n", shmsz1, shmsz2, shmsz3);
//printf("%c\n",ShmPTR[87]);
while(ShmPTR[shmsz1] != ' ')
{
shmsz1++;
}
//printf("%d \n", shmsz1);
//printf("%c1\n",ShmPTR[shmsz1]);
split_ShmPTR[0] = (char*)malloc(shmsz1 + 1000);
strncpy(split_ShmPTR[0],ShmPTR,shmsz1);
while(ShmPTR[shmsz2] != ' ')
{
shmsz2++;
}
split_ShmPTR[1] = (char*)malloc(shmsz2-shmsz1 + 1000);
strncpy(split_ShmPTR[1],ShmPTR + shmsz1,shmsz2-shmsz1);
while(ShmPTR[shmsz3] != ' ')
{
shmsz3++;
}
split_ShmPTR[2] = (char*)malloc(shmsz3-shmsz2 + 1000);
strncpy(split_ShmPTR[2],ShmPTR + shmsz2,shmsz3-shmsz2);
split_ShmPTR[3] = (char*)malloc(size-shmsz3 + 10);
strncpy(split_ShmPTR[3],ShmPTR + shmsz3,size-shmsz3);
//printf("%s\n",split_ShmPTR[3]);
struct thread_data *my_words;
char* word_array_final[30000][2];
word_array_final[0][0] = (char*)malloc(30);
word_array_final[0][1] = (char*)malloc(8);
int q, r, flag1 = 0, count, idx = 0, z;
char buff[8];
for(t = 0; t<NUM_THREADS; t++)
{
thread_data_array[t].thread_id = t;
thread_data_array[t].msg = split_ShmPTR[t];
rc = pthread_create(&threads[t], NULL, CountWords, (void *) &thread_data_array[t]);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
//pthread_join(threads[t],(void*)&my_words);
//printf("%d %s\n", my_words->thread_id, my_words->wordary[0][0]);
}
//pthread_exit(NULL);
//printf("%s\n", thread_data_array[3].msg);
pthread_attr_destroy(&attr);
for(t = 0; t<NUM_THREADS; t++)
{
pthread_join(threads[t],(void*)&my_words);
//printf("%d %s\n", my_words->thread_id, my_words->wordary[1][0]);
//printf("%d thread\n", t);
//printf("%d",my_words->size);
if(t == 0)
{
//printf("%d %s\n", my_words->thread_id, my_words->wordary[1][0]);
for(q = 0; q < my_words->size; q++)
{
strcpy(word_array_final[idx][0], my_words->wordary[q][0]);
strcpy(word_array_final[idx][1], my_words->wordary[q][1]);
idx++;
word_array_final[idx][0] = (char*)malloc(30);
word_array_final[idx][1] = (char*)malloc(8);
//printf("%s %s\n", word_array_final[idx][0], word_array_final[idx][1]);
}
}
else
{
//printf("%d %s %d\n", my_words->thread_id, my_words->wordary[1][0], my_words->size);
for(q = 0; q<my_words->size; q++)
{
flag1 = 0;
for(r = 0; r<idx; r++)
{
if(0 == (strcmp(word_array_final[r][0],my_words->wordary[q][0])))
{
flag1 = 1;
count = atoi(my_words->wordary[q][1]) + atoi(word_array_final[r][1]);
sprintf(buff, "%d", count);
strcpy(word_array_final[r][1],buff);
}
//printf("%s %s1\n", word_array_final[idx][0], word_array_final[idx][1]);
}
if(flag1 == 0)
{
strcpy(word_array_final[idx][0],my_words->wordary[q][0]);
strcpy(word_array_final[idx][1],my_words->wordary[q][1]);
idx++;
word_array_final[idx][0]=(char*)malloc(30);
word_array_final[idx][1]=(char*)malloc(8);
}
}
}
}
out_file=fopen("output.txt","w");
for(z=0; z<idx; z++)
{
fprintf(out_file, "%s : %s\n", word_array_final[z][1], word_array_final[z][0]);
}
printf("done");
fclose(out_file);
//pthread_exit(NULL);
printf(" Client is about to exit\n");
exit(0);
}
wait(&status);
printf("Server has detected the completion of its child...\n");
shmdt((void *) ShmPTR);
printf("Server has detached its shared memory...\n");
shmctl(ShmID, IPC_RMID, NULL);
printf("Server has removed its shared memory...\n");
printf("Server exits...\n");
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("Time spent: %lf\n", time_spent);
exit(0);
}
Please help me guys any help will be surely appreciated.
I found the solution...It a silly mistake...Size of my array was less...Now its fixed...And this program can be used as a child - parent program using shared memory also having mapper and reducers.

Changing address contained by structure and its members using function (ANSI C)

[EDIT]I added all my main code and some of the external functions used by this code. The code is quite long, but in summary it sends a message to a device measuring some parameters of the water in a container, and the device responds with the corresponding value measured by the sensor.
After that the code uses this value to modify the level and temperature of water. Prints the current status of the container and makes a log.txt file.[/Edit]
I want to do a constructor object-oriented-like function in C, but the address of my structure and its members are not being changed after I malloc() them. I saw this answer Changing address contained by pointer using function and I got an idea of what my problem is, but still can't solve it.
Below is my code that is doing the constructor:
udp.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "udp.h"
#define BUF_SIZE 1000
#define HEADER_SIZE
typedef struct{
int socket;
char header[4];
float *send_value;
char *message_buffer;
}message;
void build_message(message **msg, int socket, char header[], float *send_value){
*msg = (message *)malloc(sizeof(message));
(*msg)->socket = socket;
strncpy((*msg)->header, header, 4);
(*msg)->send_value = send_value;
(*msg)->message_buffer = NULL;
(*msg)->message_buffer = malloc(BUF_SIZE);
//(**msg).message_buffer = (char *)(msg+sizeof(int) + sizeof(float *) + sizeof(char *)*3);
}
int prepara_socket_cliente(char *host, char *porta)
{
struct addrinfo hints;
struct addrinfo *result, *rp;
int sfd, s;
/* Obtain address(es) matching host/port */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4/ or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
s = getaddrinfo(host, porta, &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully connect(2).
If socket(2) (or connect(2)) fails, we (close the socket
and) try the next address. */
for( rp = result; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sfd == -1)
continue;
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
break; /* Success */
close(sfd);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not connect\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(result); /* No longer needed */
return sfd;
}
float receive_message(message *msg){
ssize_t nread;
int len;
//sprintf(msg->message_buffer, "%s0.0", msg->header);
len = strlen(msg->message_buffer)+1;
int rc;
if (len + 1 > BUF_SIZE){
fprintf(stderr, "Ignoring long message in argument\n");
exit(EXIT_FAILURE);
}
if((rc = write(msg->socket, msg->message_buffer, len)) != len){
printf("%d, %d\n", len, rc);
fprintf(stderr, "partial/failed write\n");
exit(EXIT_FAILURE);
}
nread = read(msg->socket, msg->message_buffer, BUF_SIZE);
if (nread == -1){
perror("read");
exit(EXIT_FAILURE);
}
return atof(msg->message_buffer+3);
}
int send_message(message *msg){
ssize_t nread;
int len;
//sprintf(msg->message_buffer, "%s%.1f", msg->header, *msg->send_value);
len = strlen(msg->message_buffer)+1;
int rc;
if (len + 1 > BUF_SIZE){
fprintf(stderr, "Ignoring long message in argument\n");
exit(EXIT_FAILURE);
}
if((rc = write(msg->socket, msg->message_buffer, len)) != len){
printf("%d, %d\n", len, rc);
fprintf(stderr, "partial/failed write\n");
exit(EXIT_FAILURE);
}
nread = read(msg->socket, msg->message_buffer, BUF_SIZE);
if (nread == -1){
perror("read");
exit(EXIT_FAILURE);
}
return 0;
}
main.c
#include<pthread.h>
#include<stdio.h>
#include<errno.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<unistd.h>
#include<math.h>
#include<time.h>
#include<termios.h>
#include"controller.h"
#include"screen.h"
#include"myIO.h"
#include"my_time.h"
#include"data_structures.h"
#include"udp.h"
#define NUM_THREADS 5
#define MAX_PARAM_SIZE 20
#define MAX_BUFFER_SIZE 1200
//variables
typedef enum {IDLE, QUIT, CHANGE_LEVEL_REF, CHANGE_TEMP_REF} command_type;
struct timespec t1;
struct timespec t2;
pthread_cond_t screen = PTHREAD_COND_INITIALIZER;
pthread_cond_t cmd = PTHREAD_COND_INITIALIZER;
pthread_cond_t barrier = PTHREAD_COND_INITIALIZER;
int count[2] = {0,0};
command_type command = IDLE;
double_buffer* log_buffer;
char* port = NULL;
char* host = NULL;;
int socket_cliente;
real Ta, Ti, No;
real T=0;
real H=0;
real Q=0;
real Nf=0;
real Ni=0;
real Na=0;
real href = 2.0;
real tref = 25.0;
pthread_mutex_t em_scan;
pthread_mutex_t em;
void init(){
port = (char *)malloc(sizeof(char)*MAX_PARAM_SIZE);
host = (char *)malloc(sizeof(char)*MAX_PARAM_SIZE);
log_buffer = build_double_buffer();
}
//threads
void *LevelControl(void *threadid){
/**********************************************************
*thread responsible for controling the water level
*********************************************************/
controller* levelControl = NULL;
levelControl = build_controller();
levelControl->kp = 10000.0;
levelControl->ki = 0.0;
levelControl->kd = 0.0;
levelControl->error_thresh = 1.0;
levelControl->step_time = 0.7;
levelControl->max_actuator_value = 100.0;
levelControl->min_actuator_value = 0.0;
int intervalo = 90000000;
message *message_H = NULL;
build_message(&message_H, socket_cliente, "sh-", &H);
sprintf(message_H->message_buffer, "%s0.0", message_H->header);
message *message_Nf = NULL;
build_message(&message_Nf, socket_cliente, "anf", &Nf);
message *message_Ni = NULL;
build_message(&message_Ni, socket_cliente, "ani", &Ni);
loop_1:
if(command != QUIT){
pthread_mutex_lock(&em);
H = receive_message(message_H);
levelControl->error = href - H;
if(levelControl->error < 0.0){
levelControl->error = -levelControl->error;
Nf = PID_Update(levelControl);
Ni = 0.0;
}else{
Ni = PID_Update(levelControl);
Nf = 0.0;
}
sprintf(message_Nf->message_buffer, "%s%f", message_Nf->header, *message_Nf->send_value);
send_message(message_Nf);
sprintf(message_Ni->message_buffer, "%s%f", message_Ni->header, *message_Ni->send_value);
send_message(message_Ni);
count[1] = 1;
if((count[0] == 1) & (count[1] == 1)) pthread_cond_signal(&barrier);
next_timer(t1, intervalo);
pthread_mutex_unlock(&em);
goto loop_1;
}else return NULL;
}
void *TempControl(void *threadid){
/**********************************************************
* thread responsible for controling the temperature
*********************************************************/
controller *tempControl = NULL;
tempControl = build_controller();
tempControl->kp = 10000.0;
tempControl->ki = 0.0;
tempControl->kd = 0.0;
tempControl->error_thresh = 20.0;
tempControl->step_time = 0.7;
tempControl->max_actuator_value = 10000.0;
tempControl->min_actuator_value = 0.0;
int intervalo = 70000000;
message *message_T = NULL;
build_message(&message_T, socket_cliente, "st-", &T);
sprintf(message_T->message_buffer, "%s0.0", message_T->header);
message *message_Q = NULL;
build_message(&message_Q, socket_cliente, "aq-", &Q);
message *message_Na = NULL;
build_message(&message_Na, socket_cliente, "ana", &Na);
char *log_string = NULL;
log_string = (char *)malloc(sizeof(char)*MAX_BUFFER_SIZE);
// while(command != QUIT){
loop_2:
if(command != QUIT){
pthread_mutex_lock(&em);
T = receive_message(message_T);
tempControl->error = tref - T;
Q = PID_Update(tempControl);
sprintf(message_Q->message_buffer, "%s%f", message_Q->header, *message_Q->send_value);
send_message(message_Q);
if(Q == tempControl->max_actuator_value){
Na = 10.0;
}else if(Q == tempControl->min_actuator_value){
Na = 0.0;
}
sprintf(message_Na->message_buffer, "%s%f", message_Na->header, *message_Na->send_value);
send_message(message_Na);
count[0] = 1;
if((count[0] == 1) & (count[1] == 1)) pthread_cond_signal(&barrier);
pthread_mutex_unlock(&em);
sprintf(log_string, "Temperura: %f\n", T);
setDoubleBuffer(log_buffer, log_string);
next_timer(t2, intervalo);
goto loop_2;
}else return NULL;
// pthread_exit(NULL);
}
void *Status(void *threadid){
/**********************************************************
*thread responsible for printing the current status on
*the screen and setting tref and href
*********************************************************/
message *message_Ta = NULL;
build_message(&message_Ta, socket_cliente, "sta", &Ta);
sprintf(message_Ta->message_buffer, "%s0.0", message_Ta->header);
message *message_Ti = NULL;
build_message(&message_Ti, socket_cliente, "sti", &Ti);
sprintf(message_Ti->message_buffer, "%s0.0", message_Ti->header);
message *message_No = NULL;
build_message(&message_No, socket_cliente, "sno", &No);
sprintf(message_No->message_buffer, "%s0.0", message_No->header);
pthread_mutex_lock(&em);
while((count[0] != 1) | (count[1] != 1)) pthread_cond_wait(&barrier, &em);
pthread_mutex_unlock(&em);
//while(command != QUIT){
loop_3:
switch(command){
case IDLE:
pthread_mutex_lock(&em);
clearScreen();
Ta = receive_message(message_Ta);
Ti = receive_message(message_Ti);
No = receive_message(message_No);
printf("/********************************************************************************************************\n");
printf("*STATUS\n");
printf("*reference temperature: %f\n", tref);
printf("*reference water level: %f\n", href);
printf("*current temperature: %f\n", T);
printf("*current water level: %f\n", H);
printf("*other sensor value => Ni = %f, No = %f, Na = %f, Nf = %f, Ta = %f, Ti = %f\n", Ni, No, Na, Nf, Ta,Ti);
printf("*\n");
printf("*\n");
printf("*\n");
printf("*(q)uit, change (l)evel reference, change (t)emperature reference\n");
pthread_mutex_unlock(&em);
sleep(1);
break;
case CHANGE_LEVEL_REF:
pthread_mutex_lock(&em_scan);
printf("insert new Level reference\n");
scanf("%f", &href);
pthread_cond_signal(&screen);
while(command != IDLE){
pthread_cond_wait(&cmd, &em_scan);
}
pthread_mutex_unlock(&em_scan);
break;
case CHANGE_TEMP_REF:
pthread_mutex_lock(&em_scan);
printf("insert new Temperature reference\n");
scanf("%f", &tref);
pthread_cond_signal(&screen);
while(command != IDLE){
pthread_cond_wait(&cmd, &em_scan);
}
pthread_mutex_unlock(&em_scan);
case QUIT:
fprintf(stderr, "get saiu\n");
return NULL;
}
goto loop_3;
//return NULL;
}
void *GetReferences(void *threadid){
/**********************************************************
*thread responsible for changing the program mode
*********************************************************/
char temp;
//while(command != QUIT){
loop_4:
temp = getch();
switch(temp){
case 'q':
command = QUIT;
printf("%c\n --------------------------------------------------------\n", temp);
return NULL;
case 'l':
pthread_mutex_lock(&em_scan);
command = CHANGE_LEVEL_REF;
pthread_cond_wait(&screen, &em_scan);
command = IDLE;
pthread_cond_signal(&cmd);
pthread_mutex_unlock(&em_scan);
break;
case 't':
pthread_mutex_lock(&em_scan);
command = CHANGE_TEMP_REF;
pthread_cond_wait(&screen, &em_scan);
command = IDLE;
pthread_cond_signal(&cmd);
pthread_mutex_unlock(&em_scan);
}
goto loop_4;
}
void *Log(void *threadid){
char *receive_buffer = NULL;
receive_buffer = (char *)malloc(sizeof(char)*MAX_BUFFER_SIZE);
//while(command != QUIT){
loop_5:
if(command != QUIT){
get_buffer(receive_buffer, log_buffer);
write_log(receive_buffer);
goto loop_5;
}else return NULL;
}
int main (int argc, char *argv[]){
init();
pthread_mutex_init(&em_scan, NULL);
pthread_mutex_init(&em, NULL);
init_nano_timer(t1);
init_nano_timer(t2);
clearScreen();
printf("Enter the port where to be used in the udp communication\n");
scanf("%s", port);
strcpy(host, "localhost");
socket_cliente = prepara_socket_cliente(host, port);
pthread_t threads[NUM_THREADS];
int rc;
int t;
void *threadName[NUM_THREADS];
threadName[0] = TempControl;
threadName[1] = LevelControl;
threadName[2] = Status;
threadName[3] = GetReferences;
threadName[4] = Log;
for(t=0; t<NUM_THREADS; t++){
rc = pthread_create(&threads[t], NULL, threadName[t], (void *)t);
if(rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(1);
}
}
for(t=0; t<NUM_THREADS; t++){
rc = pthread_join(threads[t], NULL);
if(rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(1);
}
}
return 0;
}
Btw, I am using threads in these code, would this code be thread-safe even without mutexes?
As #Sourav Ghosh rightly commented you:
void build_message(message **msg, int socket, char header[], float *send_value)
{
*msg = malloc(sizeof(message));
(*msg)->socket = socket;
strncpy((*msg)->header, header, 4);
(*msg)->send_value = send_value;
(*msg)->message_buffer = malloc(BUF_SIZE);
}
Change the structure to:
typedef struct{
int socket;
char header[4];
float *send_value;
char *message_buffer;
}message;

segmentation fault occur on thread program

I am new in thread program. I wrote a C program for executing threads which reverse the command line string and print the both original and reversed string. My program is here:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<pthread.h>
#include<string.h>
typedef struct
{
char *input_string;
char *rev_string;
}data;
void* rev_string(void* arg)
{
int len = 0,index1 = 0,
index2 = 0;
data* names = NULL; /*bject creation*/
names = (data*)malloc(sizeof(data));
if( NULL == names)
{
printf("malloc failure\n");
exit(1);
}
printf("thread recvd = %s\n",(char*)arg);
len = strlen((char*)arg);
names->input_string = (char*)malloc(sizeof(char)*(len+1));
if( NULL == names->input_string)
{
printf("malloc failure\n");
exit(1);
}
strncpy(names->input_string,(char*)arg,len); /*copying input_string to the struct*/
names->rev_string = (char*)malloc(sizeof(char)*(len+1));
if( NULL == names->rev_string)
{
printf("malloc failure\n");
exit(1);
}
for(index1 = len-1 ; index1 >= 0 ; index1--)
{
names->rev_string[index2] = names->input_string[index1];
index2++;
}
pthread_exit((void*)names);
}
Main program:
int main(int argc,char* argv[])
{
int no_of_strings = 0,
len = 0,
status = 0,
ret = 0 ,
index = 0;
pthread_t id[index]; /*thread identifier*/
void* retval = NULL; /*retval to store the value returned by thread job */
data *strings = NULL;/*object creation*/
if(1 >= argc)
{
printf(" please do enter the commands as of below shown format\n");
printf("<exe.c> <string1> <string2> ...<string(N)>\n");
exit(1);
}
no_of_strings = argc - 1 ; /* no of strings entered */
/*creation of threads*/
for(index = 0; index < no_of_strings ;index++)
{
status = pthread_create(&id[index],NULL,rev_string,(void*)argv[index + 1]);
if(status != 0)
{
printf("ERROR in creating thread\n");
exit(1);
}
else
{
printf("thread %d created\n",index+1); }
}
for(index = 0 ;index < no_of_strings;index++)
{
ret = pthread_join(id[index],&retval);
if(ret)
{
printf("Error in joining %d\n", ret);
exit(1);
}
printf("the input_string = %s and its reverse = %s\n",((data*)retval)->input_string,((data*)retval)->rev_string);
}
// free(retval->input_string);
// free(retval->rev_string);
// free(retval);
pthread_exit(NULL);
exit(0);
}
It works on 2 string from command line argument. But got segmentation fault when more than strings. Why? Any errors? Help me.
pthread_t id[index];
id has zero length because index == 0. So any assignment to its elements is undefined behavior. Initialize the array with some positive length, e.g:
const int MAX_THREADS = 10;
pthread_t id[MAX_THREADS]; /*thread identifier*/

pthread_join leads to segmentation fault. why?

This code receives a input file with 10 filenames, stores them into an 2d array and creates 10+1 threads: a requester and 10 converters. This is only a skeleton, so my threads only print their id, thei're not accessing any global or shared variable or something that requires a mutex. So, what should I do to avoid a segmentation fault here?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <time.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/time.h>
#include <math.h>
#include <unistd.h>
#include <errno.h>
#define READ_BUFFER_LEN 16
//#define MAX_LENGTH 128
enum {
MAX_LENGTH = 512
};
typedef struct FileNameArray {
size_t nfiles; /* Number of file names allocated and in use */
size_t maxfiles; /* Number of entries allocated in array */
char **files; /* Array of file names */
} FileNameArray;
//GLOBAL vars
int num_images, *threads_ids /*threads ids*/;
pthread_t *threads;
void deallocate2D(FileNameArray *names) {
size_t i;
for (i = 0; i < names->nfiles; i++)
free(names->files[i]);
free(names->files);
names->nfiles = 0;
names->files = 0;
names->maxfiles = 0;
}
int readInputFile(FILE *fp, FileNameArray *names) {
num_images = names->nfiles;
int max_lines = names->maxfiles;
char **file_names = names->files;
char line[MAX_LENGTH];
char **final_filenames, **array;
while (fgets(line, sizeof line, fp) != NULL) {
if (line[0] != '\n') {
/* Remove newline from end of file name */
char *nl = strchr(line, '\n');
if (nl != 0)
*nl = '\0';
if (num_images >= max_lines) {
max_lines += 100;
array = realloc(file_names, max_lines * sizeof (char*));
if (array == NULL) {
fprintf(stderr, "Error reallocating space for 2d array: %s\n",
strerror(errno));
return -1;
}
names->maxfiles = max_lines;
names->files = array;
file_names = array;
}
if ((file_names[num_images] = malloc(strlen(line) + 1)) == NULL) {
fprintf(stderr, "Error allocating space for 2d array: %s\n",
strerror(errno));
return -1;
}
names->nfiles++;
strcpy(file_names[num_images], line);
printf("name of file %d is: %s \n", num_images, file_names[num_images]);
num_images++;
}
}
printf("Num_lines: %d\n", num_images);
//realloc to number of lines in the file, to avoid wasting memory
if ((final_filenames = realloc(file_names, num_images * sizeof (char*))) == NULL) {
fprintf(stderr, "Error reallocating space for 2d array: %s\n",
strerror(errno));
return -1;
}
names->maxfiles = num_images;
names->files = final_filenames;
return 0;
}
void* requester(void* arg) {
printf("This is the requester thread\n");
//sleep(1);
pthread_exit(NULL);
return NULL;
}
void* converter(void *id) {
int my_id = *((int*) id);
printf("Thread's id is: %d\n", my_id);
pthread_exit(NULL);
return NULL;
}
int main(int argc, char *argv[]) {
FileNameArray names = {0, 0, 0};
int i, rc;
pthread_attr_t attr;
//check parameters
if (argc < 4) {
fprintf(stderr, "Usage: %s input_filename.ppm charWidth charHeight\n",
argv[0]);
return -1;
}
printf("Opening input file [%s]\n", argv[1]);
FILE *fpin = fopen(argv[1], "r");
if (fpin == NULL) {
fprintf(stderr, "Could not open input file %s (%s)\n",
argv[1], strerror(errno));
return -1;
}
if ((names.files = malloc(10 * sizeof (char*))) == NULL) {
fprintf(stderr, "Error allocating initial space for 2d array: %s\n",
strerror(errno));
return -1;
}
names.maxfiles = 10;
if (readInputFile(fpin, &names) == -1) {
fprintf(stderr, "Error reading image filenames from input\n");
return -1;
}
threads = (pthread_t*) malloc(num_images + 1 * sizeof (pthread_t));
threads_ids = (int*) malloc(num_images + 1 * sizeof (int));
/* Initialize and set thread detached attribute */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
//creates requester thread, the 1st one on the list
pthread_create(&threads[0], &attr, requester, &threads_ids[0]);
threads_ids[0] = 0;
//creates so many converter threads as the number of images to convert
for (i = 1; i < num_images + 1; i++) {
threads_ids[i] = i;
rc = pthread_create(&threads[i], &attr, converter, &threads_ids[i]);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Free attribute and wait for the other threads */
pthread_attr_destroy(&attr);
for (i = 0; i < num_images + 1; i++) {
printf("Waiting for thread nr %d\n", i);
rc = pthread_join(threads[i], NULL);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
}
fclose(fpin);
free(threads);
free(threads_ids);
printf("###########\n");
deallocate2D(&names);
printf("Done!\n");
return 0;
}
This is one of the possible ouputs:
Num_lines: 10
This is the requester thread
Thread's id is: 1
Thread's id is: 2
Thread's id is: 3
Thread's id is: 5
Thread's id is: 4
Thread's id is: 6
Thread's id is: 7
Thread's id is: 8
Thread's id is: 9
Waiting for thread nr 0
Thread's id is: 10
Segmentation fault
and this is the result of gdb:
Program received signal SIGSEGV, Segmentation fault.
0x001bfea9 in *__GI___libc_free (mem=0x804c278) at malloc.c:3724
3724 malloc.c: No such file or directory.
in malloc.c
(gdb) where
#0 0x001bfea9 in *__GI___libc_free (mem=0x804c278) at malloc.c:3724
#1 0x00120802 in *__GI__dl_deallocate_tls (tcb=<value optimized out>,
dealloc_tcb=112) at dl-tls.c:487
#2 0x00133748 in __free_stacks (limit=41943040) at allocatestack.c:274
#3 0x00133849 in queue_stack (pd=0xb5fd9b70) at allocatestack.c:302
#4 __deallocate_stack (pd=0xb5fd9b70) at allocatestack.c:740
#5 0x00134b37 in pthread_join (threadid=3053296496, thread_return=0x0)
at pthread_join.c:110
#6 0x0804955c in main (argc=4, argv=0xbffff4a4) at main.c:261
threads = (pthread_t*) malloc(num_images + 1 * sizeof (pthread_t));
threads_ids = (int*) malloc(num_images + 1 * sizeof (int));
Certainly you must have intended to write
threads = malloc((num_images + 1) * sizeof (pthread_t));
threads_ids = malloc((num_images + 1) * sizeof (int));
or
threads = calloc(num_images + 1, sizeof (pthread_t));
threads_ids = calloc(num_images + 1, sizeof (int));
instead?

Resources