Reputation: 11
So a foreword, I am new to C, so please forgive any horrifying mistakes my program has.
I am trying to write a program that will take a list of numbers passed in as arguments to the program or contained in a file whose path is passed in.
It stores the numbers into an array, and stores how many numbers there are into the first element of the array. It will only store up to 100 numbers.
It then creates a pthread and passes the pointer to the array to the thread.
The thread is then suppose to sum up the numbers and return the sum back to the main function.
I am experiencing the following issues:
1. It doesn't always happen, but sometimes I get a segmentation fault right before the line of code that says:
printf("Begining to create the thread");
2. My attempts to return the sum isn't working, and after hours of research online, I can't figure out why.
3. When I compile the program, I get the following errors:
gcc -g -o assn3 assn3.c -pthread
assn3.c: In function ‘AddUpNumbers’:
assn3.c:34:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
return (void*)total;
^
assn3.c: In function ‘main’:
assn3.c:96:3: warning: passing argument 1 of ‘pthread_join’ makes integer from pointer without a cast [enabled by default]
pthread_join(&functionThread, &total);
^
In file included from assn3.c:12:0:
/usr/include/pthread.h:261:12: note: expected ‘pthread_t’ but argument is of type ‘pthread_t *’
extern int pthread_join (pthread_t __th, void **__thread_return);
^
assn3.c:97:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘void *’ [-Wformat=]
printf("The total returned by the thread is %d", total);
^
Here's my code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NO_ARGS 1
#define ONLY_SINGLE_ARG 2
#define PATH_TO_READ_FROM 1
#define MAX_NUMBERS 101
#define MAX_CHAR_INPUT 255
#define COUNT_LOCATION 0
void* AddUpNumbers(void* arrayPointer) {
printf("Created the pthread!");
int* numbersArray = (int*)arrayPointer;
int count = numbersArray[COUNT_LOCATION];
int total = 0;
int i = 1;
while (i < count) {
total = total + numbersArray[i];
}
printf("The total to be returned is %d", total);
return (void*)total;
}
int main(int argc, char* argv[]) {
FILE * numbersFile = NULL;
int count = 0;
int numberArray[MAX_NUMBERS];
//Initialize the Array
int i = 0;
while (i < MAX_NUMBERS) {
numberArray[i] = 0;
i = i + 1;
}
if (argc == NO_ARGS) {
printf("Usage: # or file path, #, #, ..., #\n");
} else if (argc == ONLY_SINGLE_ARG) {
numbersFile = fopen(argv[PATH_TO_READ_FROM], "r");
if (numbersFile != NULL) {
char buff[MAX_CHAR_INPUT];
i = 1;
count = 0;
while (i < MAX_NUMBERS) {
if (fscanf(numbersFile, "%s", buff) != EOF) {
numberArray[i] = atoi(buff);
printf("%d\n", numberArray[i]);
i = i + 1;
count = count + 1;
} else {
break;
}
}
numberArray[COUNT_LOCATION] = count;
printf("Count Total: %d\n", numberArray[COUNT_LOCATION]);
} else {
printf("Error: Could not open file!\n");
return -1;
}
} else if (argc < MAX_NUMBERS + 1) {
i = 1;
count = 0;
while (i < argc) {
numberArray[i] = atoi(argv[i]);
printf("%d\n", numberArray[i]);
i = i + 1;
count = count + 1;
}
printf("See if error happens after this");
numberArray[COUNT_LOCATION] = count;
printf("Count Total: %d\n", numberArray[COUNT_LOCATION]);
} else {
printf("Too many numbers! This program can only add up to: %d numbers.\n", MAX_NUMBERS);
return -1;
}
printf("Begining to create the thread");
pthread_t functionThread;
int creationSuccess = 0;
void* total;
creationSuccess = pthread_create(&functionThread, NULL, AddUpNumbers, (void*)numberArray);
if (creationSuccess == 0) {
pthread_join(&functionThread, total);
printf("The total returned by the thread is %d", *((int)total));
} else {
printf("Something went wrong.\n");
}
if (numbersFile != NULL) {
fclose(numbersFile);
}
return 0;
}
My Makefile looks like this:
assn3: assn3.c
gcc -g -o assn3 assn3.c -pthread
Upvotes: 1
Views: 960
Reputation: 136
The syntax of pthread_create
is:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, *(*start_routine) (void *), void *arg);
pthread_t - is id of thread. So create variable pthread_t id
, or array of values if you have a lot of threads, like pthread_t id[THREAD_NUM];
Then your func will looks like:
pthread_create(&id[i], NULL, &functionThread, (void*)numberArray);
With pthread_join(&functionThread, total);
The same thing.
int pthread_join(pthread_t thread, void **value_ptr);
So you join must look like:
pthread_join(&id[i], total);
Upvotes: 0
Reputation: 180048
You should be very wary of compiler warnings. Either clean them up or understand very well why they are ok. Pay special attention to warnings about data type mismatches.
In this case this warning probably explains the main problem:
In file included from assn3.c:12:0: /usr/include/pthread.h:261:12: note: expected ‘pthread_t’ but argument is of type ‘pthread_t *’ extern int pthread_join (pthread_t __th, void **__thread_return); ^
You are (creating and) passing a pointer to your pthread_t
object as the first argument of pthread_join()
, but unlike pthread_create()
, pthread_join()
expects you to pass the pthread_t
itself, not a pointer to it. All manner of havoc (technically, "undefined behavior") will ensue.
UPDATE: Additionally, the second argument you are passing to pthread_join()
is an uninitialized pointer to void
. If pthread_create()
tries to write anything where it points then who knows what happens (undefined behavior again). You are expected to pass a valid pointer to the location where the result is to be written. In this case, that would be &total
.
Upvotes: 1