Segmentation fault (core dumped) in C - While Using PTHREADS - c

Hello guys,
I have a problem in my code and i do not know how to fix it(A Segmentation fault(core dumped))!
So my teacher wants me to write a program that creates N treads and makes them do some calculations.I have 3 global 2d arrays A,B,C (i have them as pointers because i don not know the size,the user gives it as argument).I try to allocate memory to them in the main function.
So the problem is i get a Segmentation fault when i try to create the treads in "pthread_create(&tid[id],NULL,add,(void *)(long) i);" :(.
I can't figure out why this is happening.I tried using the gdb command but the result was that the problem is in pthread_create.
However when i put in comment the arrays(A,B,C) and the malloc they are using is runs(but the final result is 0).
I am using a virtual box(with Ubuntu inside if that helps :D).
The following code is what i wrote so far:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
long int p,N,Total_Sum;
long int **A,**B,**C;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_barrier_t bar;
void * add(void *arg){
long int i,j,Local_Sum=0;
long int lines,start,end,id;
id = (long int)arg;
lines = N/p;
start = id*lines;
end = start+lines;
for(i=start;i<end;i++){
for(j=0;j<N;j++){
A[i][j] = 1;
B[i][j] = 1;
}
}
for(i=start;i<end;i++){
for(j=0;j<N;j++){
C[i][j] = A[i][j] * B[i][j];
Local_Sum += C[i][j];
printf("C[%ld][%ld] = %ld\n",i,j,C[i][j]);
}
}
pthread_mutex_lock(&mutex);
Total_Sum += Local_Sum;
pthread_mutex_unlock(&mutex);
pthread_barrier_wait(&bar);
pthread_exit(0);
}
int main(int argc, char *argv[]){
long int i,j,id;
pthread_t *tid;
if(argc!=3){
printf("Provide Number Of Threads And Size\n");
exit(1);
}
p = atoi(argv[1]);
tid = (pthread_t *) malloc(p*sizeof(pthread_t));
if(tid == NULL){
printf("Could Not Allocate Memory\n");
exit(1);
}
pthread_barrier_init(&bar,NULL,p);
N = atoi(argv[2]);
A = (long int**) malloc(N*sizeof(long int*));
B = (long int**) malloc(N*sizeof(long int*));
C = (long int**) malloc(N*sizeof(long int*));
for(i=0;i<N;i++){
A[i] = (long int*) malloc(N*sizeof(long int));
B[i] = (long int*) malloc(N*sizeof(long int));
C[i] = (long int*) malloc(N*sizeof(long int));
}
if((A==NULL) || (B == NULL) || (C == NULL)){
printf("Count Not Allocate Memory\n");
exit(1);
}
for(i=0;i<p;i++){
pthread_create(&tid[id],NULL,add,(void *)(long) i);
}
for(i=0;i<p;i++){
pthread_join(tid[id],NULL);
}
for(i=0;i<N;i++){
free(A[i]);
free(B[i]);
free(C[i]);
}
free(A);
free(B);
free(C);
printf("Final Result Is Equal To: %ld\n",Total_Sum);
return 0;
}
******I know it gets a little bit messy because of the mutex and the the barriers but ask me for further specifications :D.******
Thanks!!!!!!

I think the only problem are the indexes in the following lines:
for(i=0;i<p;i++){
pthread_create(&tid[id],NULL,add,(void *)(long) i);
}
for(i=0;i<p;i++){
pthread_join(tid[id],NULL);
}
id has only been declared, but never initialized! Maybe it's just a typo and you wanted to use i as index for the tid
The solutions should be:
for(i=0;i<p;i++){
pthread_create(&tid[i],NULL,add,(void *)(long) i);
}
for(i=0;i<p;i++){
pthread_join(tid[i],NULL);
}

The answer to the source of your core dump problem has already been addressed, but to address the other things you asked, or stated:
1st:
Regarding your statement: i have them as pointers because i don not know the size,the user gives it as argument.
Often times, in C, you can avoid using calloc/malloc in your code by using VLAs instead. Available in C99 and beyond. (see links)
VLA a
VLA b
2nd:
Regarding your statement: I know it gets a little bit messy...
Its really not that messy, but you could consider cleaning up the memory allocation/freeing steps by moving most of the work into a function:
long int **A,**B,**C;
int N;
...
//in main
N = atoi(argv[2]);
A = Create2D(N, N);
B = Create2D(N, N);
B = Create2D(N, N);
...
free2D(A, N);
free2D(B, N);
free2D(C, N);
long ** Create2D(int c, int r)
{
long **arr;
int y = 0;
arr = calloc(c, sizeof(long *));
for(y=0;y<c;y++)
{
arr[y] = calloc((2*y)+1, sizeof(long));
}
return arr;
}
void free2D(long **arr, int c)
{
int i;
if(!arr) return;
for(i=0;i<c;i++)
{
if(arr[i])
{
free(arr[i]);
arr[i] = NULL;
}
}
free(arr);
arr = NULL;
}
Side note:
There is nothing absolutely wrong with your memory statements as they are:
A = (long int**) malloc(N*sizeof(long int*));
However, although C++ requires it, there is no reason to cast the return of malloc ,calloc or realloc when using C. (See discussion here) The following is sufficient (in C):
A = malloc(N*sizeof(long int*));

Related

Array of 20000000 elements limits [duplicate]

This question already has answers here:
Segmentation fault on large array sizes
(7 answers)
Closed 4 years ago.
For a university project, I have to sort a CSV file of 20 million records (wich are represented in 2^64 bit, for example, 10000000 or 7000000, so I used unsigned long long) using MergeSort. So, I developed this C file:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// Path to the dataset
#define DATASET_PATH "/Volumes/HDD/Lorenzo/Unito/2 Anno/ASD/Progetto/Progetto 2017-2018/laboratorio-algoritmi-2017-18/Datasets/ex1/integers.csv"
#define ELEMENTS_TO_SCAN 1000000 // the numbers of elements to be scanned
void mergeSort(unsigned long long * arrayToSort, int leftIndex, int rightIndex);
void merge(unsigned long long * arrayToSort, int left, int center, int right);
void read();
void printArray();
// from "Introduction to Algorithms" of T. H. Cormen
void mergeSort(unsigned long long * arrayToSort, int leftIndex, int rightIndex){
if(leftIndex < rightIndex){
int center = (leftIndex + rightIndex) / 2;
mergeSort(arrayToSort, leftIndex, center);
mergeSort(arrayToSort, center + 1, rightIndex);
merge(arrayToSort, leftIndex, center, rightIndex);
}
}
// from "Introduction to Algorithms" of T. H. Cormen
void merge(unsigned long long * arrayToSort, int left, int center, int right){
int n1 = center - left + 1;
int n2 = right - center;
unsigned long long leftSubArray[n1+1];
unsigned long long rightSubArray[n2+1];
leftSubArray[n1] = ULLONG_MAX; // here Cormen use infinite
rightSubArray[n2] = ULLONG_MAX; // here Cormen use infinite
for(int i = 0; i < n1; i++)
leftSubArray[i] = arrayToSort[left + i];
for(int j = 0; j < n2; j++)
rightSubArray[j] = arrayToSort[center + j + 1];
int i = 0;
int j = 0;
int k = 0;
for(k = left; k <= right; k++){
if(leftSubArray[i] <= rightSubArray[j]){
arrayToSort[k] = leftSubArray[i];
i++;
} else {
arrayToSort[k] = rightSubArray[j];
j++;
}
}
}
// it reads all the dataset, and saves every line (wich contains a single element)
// in a position of an array to sort by MergeSort.
void read(char pathToDataset[], unsigned long long arrayToFill[]) {
FILE* dataset = fopen(pathToDataset, "r");
if(dataset == NULL ) {
printf("Error while opening the file.\n");
exit(0); // exit failure, it closes the program
}
int i = 0;
while (i < ELEMENTS_TO_SCAN && fscanf(dataset, "%llu", &arrayToFill[i])!=EOF) {
//printf("%llu\n", arrayToFill[i]); // ONLY FOR DEBUG, it wil print 20ML of lines!
i++;
}
printf("\nRead %d lines.\n", i);
fclose(dataset);
}
void printArray(unsigned long long * arrayToPrint, int arrayLength){
printf("[");
for(int i = 0; i < arrayLength; i++) {
if (i == arrayLength-1) {
printf("%llu]", arrayToPrint[i]);
}
else {
printf("%llu, ", arrayToPrint[i]);
}
}
}
int main() {
unsigned long long toSort [ELEMENTS_TO_SCAN] = {};
read(DATASET_PATH, toSort);
mergeSort(toSort,0,ELEMENTS_TO_SCAN-1);
printf("Merge finished\n");
return 0;
}
after some testing, if ELEMENTS_TO_SCAN is bigger than 500000 (= 1/4 of 20 million) i don't know why, but the output on the terminal is
Segmentation fault: 11
Someone can help me?
You’re doing a local variable declaration (eg on stack). If you’re dealing with larger arrays, consider making them global, or use dynamic arrays — in general dynamic would be better. Using globals makes it easier to get into bad habits.
Why are global variables bad, in a single threaded, non-os, embedded application
Segmentation fault 11 because of a 40 MB array in C
As people pointed out, this type of allocation can't be done on Stack. I would try dynamically allocating it, for that you just need to change the code like so:
int main() {
unsigned long long *toSort;
toSort = (unsigned long long) malloc(ELEMENTS_TO_SCAN*sizeof(unsigned long long));
read(DATASET_PATH, toSort);
mergeSort(toSort,0,ELEMENTS_TO_SCAN-1);
printf("Merge finished\n");
free(toSort);
return 0;
}
As you pointed the merge is the one causing problems. Just to note, if you use things like:
int array[n];
You will run into problems eventually, that's a given. If you don't know how much memory you will use at compile time, either use a data structure that supports the resizing like linked lists or dynamically allocate it .

Input of integers' array of unknown size

I'm trying to create an array of integers of an unknown size.
Every time I input a positive element I use realloc to increase the size of the array and store that element
The thing is that when I run this code, I get a run-time error after 2 iterations of the while of the function create1DArray, so it's probably due to a realloc failure.
Can anybody tell me what I did wrong and how to fix it?
Thanks in advance,
#include <stdio.h>
#include <stdlib.h>
void create1DArray(int** perArray, int* size);
int main()
{
int *perArray, size=0, i;
create1DArray(&perArray, &size );
for(i=0; i<size; i++)
printf("%d ",perArray[i]);
free(perArray);
return 0;
}
void create1DArray(int** perArray, int* size)
{
int flag=0, i=0, x;
*perArray=(int*)malloc(sizeof(int) );
if(*perArray==NULL)
{
printf("Allocation failed!");
exit(1);
}
while(!flag)
{
if( scanf("%d", &x)<1 || (x<0) )
{
printf("Invalid input!");
free(perArray);
exit(1);
}
if(!x)
{
if( !(*size) )
{
printf("The first element of the array must not be 0");
free(perArray);
exit(1);
}
flag++;
}
else
{
*perArray=(int*)realloc(*perArray, (++(*size))*sizeof(int) );
if(*perArray==NULL)
{
printf("Reallocation failed!");
free(perArray);
exit(1);
}
*perArray[i++]=x;
}
}
}
I think I see two problems (and M Oehm spotted one more):
1) Your handling of size is wrong (or at least strange). Normally you'll do something like:
*perArray=(int*)malloc(sizeof(int) );
*size = 1;
Perhaps even better - you should drop the malloc and just initialize the pointer in main to NULL. realloc works like malloc when called with NULL.
This would also allow you to call the function several times - something you current code doesn't allow.
2) There is a problem with your realloc
*perArray=(int*)realloc(perArray, (++(*size))*sizeof(int) );
^^^^
Should be *perArray
3) You need to dereference the pointer before indexing (noticed by M Oehm - thanks).
*perArray[i++]=x; ---> (*perArray)[i++]=x;
May not be exactly what you want, but take a look at how it can be done concisely (although doing realloc at each iteration is inefficient). It should be compiled with the flag std=c11.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main()
{
int size = 0;
int input = 0;
int * perArray = NULL;
while(scanf("%d", &input) && input > 0)
{
++size;
perArray = (int *) realloc(perArray, sizeof(int) * (long unsigned) size);
assert(perArray);
perArray[size - 1] = input;
}
if(perArray)
{
for(int i = 0; i < size; ++i) printf("%d ", perArray[i]);
printf("\n");
free(perArray);
}
return 0;
}

Segmentation fault when using malloc for 2D array

I create a 2-D array using malloc. When I use printf to print the array element in for loop, everything is fine. But when I want to use printf in main, these is a Segmentation fault: 11.
Could you please tell me what the problem with the following code is?
#include <stdlib.h>
#include <stdio.h>
void initCache(int **cache, int s, int E){
int i, j;
/* allocate memory to cache */
cache = (int **)malloc(s * sizeof(int *)); //set
for (i = 0; i < s; i++){
cache[i] = (int *)malloc(E * sizeof(int)); //int
for(j = 0; j < E; j++){
cache[i][j] = i + j;
printf("%d\n", cache[i][j]);
}
}
}
main()
{
int **c;
initCache (c, 2, 2);
printf("%d\n", c[1][1]); // <<<<<<<<<< here
}
Since your cache is a 2D array, it's int**. To set it in a function, pass int***, not int**. Otherwise, changes to cache made inside initCache have no effect on the value of c from main().
void initCache(int ***cache, int s, int E) {
int i, j;
/* allocate memory to cache */
*cache = (int **)malloc(s * sizeof(int *)); //set
for (i = 0; i < s; i++) {
(*cache)[i] = (int *)malloc(E * sizeof(int)); //int
for(j = 0; j < E; j++){
(*cache)[i][j] = i + j;
printf("%d\n", (*cache)[i][j]);
}
}
}
Now you can call it like this:
initCache (&c, 2, 2);
You changed a local variable, which won't effect the local variable c in main.
If you want to allocate in the function, why pass a variable? Return it from the function.
int **c = initCache(2, 2);
You could use a return, or else a *** as suggested by others. I'll describe the return method here.
initCache is creating and initializing a suitable array, but it is not returning it. cache is a local variable pointing to the data. There are two ways to make this information available to the calling function. Either return it, or pass in an int*** and use that to record the pointer value.
I suggest this:
int** initCache(int **cache, int s, int E){
....
return cache;
}
main()
{
int **c;
c = initCache (2, 2);
printf("%d\n", c[1][1]); <<<<<<<<<< here
}
====
Finally, it's very important to get in the habit of checking for errors. For example, malloc will return NULL if it has run out of memory. Also, you might accidentally as for a negative amount of memory (if s is negative). Therefore I would do:
cache = (int **)malloc(s * sizeof(int *));
assert(cache);
This will end the program if the malloc fails, and tell you what line has failed. Some people (including me!) would disapprove slightly of using assert like this. But we'd all agree it's better than having no error checking whatsoever!
You might need to #include <assert.h> to make this work.

Access violation when using free() when running but not when debugging... slowly

As per my previous question (many thanks to Jonathan Leffler), I edited my code (second two blocks of code), but I ran into a rather strange problem.
The following one breaks unpredictably...
void free_array(array_info *A)
{
int i;
for(i = 0; i < (A->height); ++i)
{
printf("About to free: %x\n", A->dat_ptr[i]);//for debugging purposes
free(A->dat_ptr[i]);
printf("Freed row %i\n", i);//for debugging purposes
}
free(A->dat_ptr);
}
I initially tested create_array directly followd by free_array and it worked flawlessly with rather big arrays (10^8). However, when I do my calculations in between and then try to free() the arrays, I get an access violation exception (c00000005). When I was debugging it, I noticed that the program would execute perfectly every time if I had a breakpoint within the "free_array" loop and did every line individually. However, the compiled code wouldn't ever run past row6 of my second array on its own. I turned off all optimisations in the compiler, and I still got the error upon execution.
Additional info
typedef struct {
int height;
int width;
int bottom;//position of the bottom tube/slice boundary
unsigned int** dat_ptr;//a pointer to a 2d array
} array_info;
Where the dat_ptr is now a proper 2D pointer. The create_array function that creates the array that is to be put in the structure is (i have stripped NULL checks for readability):
int create_array(array_info *A)
{
int i;
unsigned int **array = malloc(sizeof(*array) * A->height);
for (i = 0; i < A->height; ++i)
{
array[i] = malloc(sizeof(**array) * A->width);
}
A->dat_ptr = array;
return 0;
}
This function works exactly as expected.
More Additional Info
Added after the responses of Jonathan, Chris, and rharrison33
Thank you so much, Jonathan, with every one of your posts I find out so much about programming :) I finally found the culprit. The code causing the exception was the following:
void fill_number(array_info* array, int value, int x1, int y1, int x2, int y2)//fills a rectangular part of the array with `value`
{
int i, j;
for(i=y1 ; ((i<=y2)&&(i<array->height)) ; i++)//start seeding the values by row (as in vertically)
{
for(j=x1 ; ((i<=x2)&&(i<array->width)) ; j++)//seed the values by columns (as in horizontally)
{
array->dat_ptr[i][j]=value;
}
}
}
And ((i<=x2)&&(i<=array->width)) wasn't being evaluated as I expected (Chris Dodd, you were right). I thought that it would evaluate both conditions in that order or stop if either was "FALSE", independent of their order. However, it turned out it didn't work that way and it was simply refusing to evaluate the (i<array->width) part correctly. Also, I assumed that it would trigger an exception upon trying to access memory outside of the array range, but it didn't. Anyway,
I changed the code to:
void fill_number(array_info* array, int value, int x1, int y1,
int x2, int y2)
{
int i, j;
if(y1>=array->height){ y1=array->height-1;}
if(y2>=array->height){ y1=array->height-1;}
if(x1>=array->width) { x2=array->width-1;}
if(x2>=array->width) { x2=array->width-1;}
for(i=y1 ; i<=y2 ; i++)//start seeding the values by row
{
for(j=x1 ; j<=x2 ; j++)//seed the values by column
{
array->dat_ptr[i][j]=value;
}
}
}
And now it works. The block of if()s is there because I won't be calling the function very often compared to the rest of the code and I need a visual way to remind me that the check is there.
Again, thank you so much Jonathan Leffler, Chris Dodd, and rharrison33 :)
This code, closely based on what you've gotten from me and what you wrote above, seems to be working as expected. Note the use of <inttypes.h> and PRIXPTR (and the cast to (uintptr_t)). It avoids making assumptions about the size of pointers and works equally well on 32-bit and 64-bit systems (though the %.8 means you get full 8-digit hex values on 32-bit compilations, and 12 (out of a maximum of 16) on this specific 64-bit platform).
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
typedef struct
{
int height;
int width;
int bottom;
unsigned int **dat_ptr; // Double pointer, not triple pointer
} array_info;
static void create_array(array_info *A)
{
unsigned int **array = malloc(sizeof(*array) * A->height);
printf("array (%zu) = 0x%.8" PRIXPTR "\n",
sizeof(*array) * A->height, (uintptr_t)array);
for (int i = 0; i < A->height; ++i)
{
array[i] = malloc(sizeof(**array) * A->width);
printf("array[%d] (%zu) = 0x%.8" PRIXPTR "\n",
i, sizeof(**array) * A->width, (uintptr_t)array[i]);
}
A->dat_ptr = array;
}
static void free_array(array_info *A)
{
int i;
for(i = 0; i < (A->height); ++i)
{
printf("About to free %d: 0x%.8" PRIXPTR "\n",
i, (uintptr_t)A->dat_ptr[i]);
free(A->dat_ptr[i]);
}
printf("About to free: 0x%.8" PRIXPTR "\n", (uintptr_t)A->dat_ptr);
free(A->dat_ptr);
}
int main(void)
{
array_info array = { .height = 5, .width = 10, .dat_ptr = 0 };
create_array(&array);
if (array.dat_ptr == 0)
{
fprintf(stderr, "Out of memory\n");
exit(1);
}
free_array(&array);
puts("OK");
return(0);
}
Sample output
array (40) = 0x7FAFB3C03980
array[0] (40) = 0x7FAFB3C039B0
array[1] (40) = 0x7FAFB3C039E0
array[2] (40) = 0x7FAFB3C03A10
array[3] (40) = 0x7FAFB3C03A40
array[4] (40) = 0x7FAFB3C03A70
About to free 0: 0x7FAFB3C039B0
About to free 1: 0x7FAFB3C039E0
About to free 2: 0x7FAFB3C03A10
About to free 3: 0x7FAFB3C03A40
About to free 4: 0x7FAFB3C03A70
About to free: 0x7FAFB3C03980
OK
I've not got valgrind on this machine, but the addresses being allocated and freed can be eyeballed to show that there's no obvious problem there. It's coincidence that I sized the arrays such that they're all 40 bytes (on a 64-bit machine).
Follow-up Questions
What else are you doing with your data?
How big are the arrays that you're allocating?
Are you sure you're not running into arithmetic overflows?
Testing on Mac OS X 10.8.2 and the XCode version of GCC/Clang:
i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
Array setting and printing functions
static void init_array(array_info *A)
{
unsigned int ctr = 0;
printf("D = 0x%.8" PRIXPTR "\n", (uintptr_t)A->dat_ptr);
for (int i = 0; i < A->height; i++)
{
printf("D[%d] = 0x%.8" PRIXPTR "\n",i, (uintptr_t)A->dat_ptr[i]);
for (int j = 0; j < A->width; j++)
{
printf("D[%d][%d] = 0x%.8" PRIXPTR " (%u)\n",
i, j, (uintptr_t)&A->dat_ptr[i][j], ctr);
A->dat_ptr[i][j] = ctr;
ctr += 7;
}
}
}
static void print_array(array_info *A)
{
printf("D = 0x%.8" PRIXPTR "\n", (uintptr_t)A->dat_ptr);
for (int i = 0; i < A->height; i++)
{
printf("D[%d] = 0x%.8" PRIXPTR "\n",i, (uintptr_t)A->dat_ptr[i]);
for (int j = 0; j < A->width; j++)
{
printf("D[%d][%d] = 0x%.8" PRIXPTR " (%u)\n",
i, j, (uintptr_t)&A->dat_ptr[i][j], A->dat_ptr[i][j]);
}
}
}
With a call init_array(&array); in main() after the successful create_array() and a call to print_array(&array); after that, I got the expected output. It's too boring to show here.
I believe you are malloc'ing incorrectly. Try modifying your create_array function to this:
int create_array(array_info *A)
{
int i;
unsigned int **array = malloc(sizeof(unsigned int*) * A->height);
for (i = 0; i < A->height; ++i)
{
array[i] = malloc(sizeof(unsigned int) * A->width);
}
A->dat_ptr = array;
return 0;
}

Multithreading in C, get the average of 4 arrays

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,
In
*result = *som1 + *som2 + *som3 + *som4;
result is used unitialized. Make it a plain float instead of a pointer.
From your current code, segfault occurs because som* aren't initialized -- they are dangling pointers.
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;
}

Resources