Multithreading in C, get the average of 4 arrays

1k views Asked by At

I'm new to multithreading had my first lesson yesterday. So I've wrote a program to get the average of 4 big arrays , each array is a thread and the main waits for all the threads and gives the average of the 4 arrays. This is possible because each thread gives the average of one array. The array is just a headerfile with a float array.

It compiles but gives me a segmentation error and I don't see why.

    #include "gemiddelde.h"
#include <stdlib.h>
#include <stdio.h>

float *gemiddelde(void *arg)
{
    float *a;
    int i;
    a = (float *)arg;
    float  * som;

    for( i = 0; i < 100000; i++)
       *som += a[i];
    *som = *som / 100000;
    return som;
}

int main()
{
    pthread_t t1,t2,t3,t4;
    float  * som1, * som2, * som3, * som4, *result;

    pthread_create(&t1,NULL,gemiddelde,a1);
    pthread_create(&t2,NULL,gemiddelde,a2);
    pthread_create(&t3,NULL,gemiddelde,a3);
    pthread_create(&t4,NULL,gemiddelde,a4);

    pthread_join(t1,som1);
    pthread_join(t2,som2);
    pthread_join(t3,som3);
    pthread_join(t4,som4);

    usleep(1);
    *result = *som1 + *som2 + *som3 + *som4;
    printf("Gemiddelde is: %f ", *result);
    return 0;
}

Can someone help me?

Kind regards,

3

There are 3 answers

0
Fred Foo On

In

*result = *som1 + *som2 + *som3 + *som4;

result is used unitialized. Make it a plain float instead of a pointer.

2
Victor Sorokin On

From your current code, segfault occurs because som* aren't initialized -- they are dangling pointers.

0
Kerrek SB On

Your code is very problematic, because the thread code requires memory to store the result, and as it stands your code is plain wrong because it doesn't have any memory and just dereferences a dangling pointer. But even allocating memory inside the thread is not a great idea, because it's not clear who is responsible for it and who will clean it up. So it's much better to allocate all your required memory in the main function. First some boiler plate to set up the thread argument data:

 typedef struct thread_arg_type_
 {
     float * data;
     size_t  len;
     float   retval;
 } thread_arg_type;

 thread_arg_type * create_thread_arg(size_t n)
 {
     thread_arg_type * result = malloc(sizeof(thread_arg_type));
     if (!result) return NULL;

     float * const p = malloc(n * sizeof(float));
     if (!p)
     {
         free(result);
         return NULL;
     }

     result->len = n;
     result->data = p;
     return result;
 }

 void free_thread_arg(thred_arg_type * r)
 {
     if (r) free(r->data);
     free(r);
 }

Now here's how we use it:

 int main()
 {
     thread_arg_type * arg;
     pthread_t t;

     arg = create_thread_arg(array1_size);
     pthread_create(&t, NULL, getmiddle, arg);

     // ...

     pthread_join(t, NULL);
     printf("The result is: %f.\n", arg->retval);
     free_thread_arg(arg);
 }

And finally we must adapt getmiddle:

void * getmiddle(thread_arg_t * arg)
{
    arg->retval = 0;

    for(unsigned int i = 0; i != arg->len; ++i)
        arg->retval += arg->data[i];

    arg->retval /= arg->len;

    return NULL;
}