Reputation: 319
When I run this code I just get a straight up Seg fault. I do not know how to fix it. I am trying to create a simple multithreading programming. It compiles completely fine but it when i run it by typing "./testing", the print statement "what?" at the beginning of the main function won't even print and just seg faults. I've been stuck on this for couple of hours now. Any ideas? Thanks
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
static pthread_mutex_t mutex1;
static pthread_mutex_t mutex2;
static int arrayX[4];
static int arrayY[4];
static pthread_t threads[20];
static void *function(void *index) {
pthread_mutex_lock(&mutex1);
int *in = (int *)index;
arrayX[*in]++;
pthread_mutex_unlock(&mutex1);
pthread_mutex_lock(&mutex2);
arrayY[*in]--;
printf("X Finished");
pthread_mutex_unlock(&mutex2);
}
void main() {
printf("what?");
//initialize the mutex
pthread_mutex_init(&mutex1, NULL);
pthread_mutex_init(&mutex2, NULL);
//Initialize the arrayX
int x = 0;
for (x; x < 4; x++) {
arrayX[x] = 0;
printf("START arrayX[%d]: %d", x, arrayX[x]);
}
//Initialize the arrayY
for (x = 0; x < 4; x++) {
arrayY[x] = 0;
printf("START arrayY[%d]: %d", x, arrayY[x]);
}
pthread_mutex_init(&mutex1, NULL);
pthread_mutex_init(&mutex2, NULL);
int *input = 0;
for (x = 0; x < 20; x++) {
*input = x % 4;
pthread_create(&(threads[x]), NULL, function, input);
}
}
Upvotes: 0
Views: 1423
Reputation: 10100
int *input = 0
is setting the memory address of input
to nullptr
, therefor you can't store data in this address because it's invalid, you can simply leave it uninitialized int *input
and then when you assign it to an int
, the compiler would choose a suitable free memory location and assign the data to it.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static pthread_mutex_t mutex1;
static pthread_mutex_t mutex2;
static pthread_t threads[20];
static int arrayX[4];
static int arrayY[4];
static void *function (void *index)
{
int in = *((int *) index);
pthread_mutex_lock (&mutex1);
arrayX[in]++;
pthread_mutex_unlock (&mutex1);
pthread_mutex_lock (&mutex2);
arrayY[in]--;
pthread_mutex_unlock (&mutex2);
// printf ("X Finished\n");
}
int main (int argc __attribute__((unused)), char **argv __attribute__((unused)))
{
int x = 0;
int *input;
printf ("what?\n");
// Initialize the mutex
pthread_mutex_init (&mutex1, NULL);
pthread_mutex_init (&mutex2, NULL);
// Initialize arrayX and arrayY
memset (arrayX, 0, sizeof (arrayX));
memset (arrayY, 0, sizeof (arrayY));
// Increment values inside arrays
for (x = 0; x < 20; x++)
{
*input = x % 4;
pthread_create (&(threads[x]), NULL, function, input);
}
// Print array values
for (x = 0; x < 4; x++) printf ("arrayX[%d]: %d\n", x, arrayX[x]);
for (x = 0; x < 4; x++) printf ("arrayY[%d]: %d\n", x, arrayY[x]);
return 0;
}
Dereferencing (which means using *
operater to asign value to an already declared pointer i.e. *ptr = something
) an uninitialized pointer (which means declaring a pointer without assigning value to it i.e. int *pointer;
) is not a good pratice, although it may work but it can cause a crash sometimes, this is because the uninitialized pointer may point to a memory address that is being used by the system will cause an Undefined Behaviour and possibly a crash. A corret approach would be to initialize the pointer to NULL
or use malloc
to get a valid pointer, however when you initialize a pointer to NULL
you can not dereference it becuase it's an invalid pointer.
So instead of doing:
int *input;
*input = x % 4;
We can do:
int *input;
input = malloc (sizeof (int));
*input = x % 4;
When sending input
pointer to one thread then changing its value and sending it to another thread, the input
value would be changed in the first thread to the new value as well, this happens because you are sharing the same pointer input
(therefore the same memory address) with all the threads. To make sure that every thread gets the intended input value you can do:
for (x = 0; x < 20; x++)
{
// Create a new valid pointer
input = malloc (sizeof (int));
*input = x % 4;
pthread_create (&(threads[x]), NULL, function, input);
}
This will pass a different pointer to each thread, However when you dynamically allocate memory using malloc
for example, you have to free this allocated memory, we can do that from within each thread:
static void *function (void *index)
{
int *in = (int *) index;
pthread_mutex_lock (&mutex1);
arrayX[*in]++;
pthread_mutex_unlock (&mutex1);
pthread_mutex_lock (&mutex2);
arrayY[*in]--;
printf ("X Finished");
pthread_mutex_unlock (&mutex2);
// Freeing the allocated memory
free (in);
}
When creating threads using pthread_creat
, the main threads terminates when it hits the end of the main
function without waiting for the other threads to finish work, unless you tell the main thread to wait for them, to do that we can use pthread_join
:
// Create new threads
for (x = 0; x < 20; x++)
{
*input = x % 4;
pthread_create (&(threads[x]), NULL, function, (void *) input);
}
// Wait for the threads to finish
for (x = 0; x < 20; x++)
{
pthread_join (threads[x], NULL);
}
This will force the main thread to keep running until all the other threads has done their work before it exits.
Upvotes: 1