Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to free memory allocated by thread-function in the main

I have allocated heap memory in the thread function f1, this storage is used to calculate the value in the heap region so that the main function can see it.

Here is the thread function definition:

void *f1(void *input){


        int sum = (int*)malloc(sizeof(int));
        /* Do calculation */   
        pthread_exit((void*)&sum);
}

In the above code, the sum is the heap allocated storage, whose address is passed as a return value to the sum1 in the main().

I join the thread in the main() like this:

void *sum1;
pthread_join(tid1,(void**)&sum1);

Once i retrieved the value, i want to free the allocated memory. When i use free in the main, it complains like munmap_chunk(): invalid pointer

How can i explicitly and safely free this memory ?

like image 486
Nouman Tajik Avatar asked Oct 16 '25 18:10

Nouman Tajik


2 Answers

You should send back the pointer, not its address

pthread_exit(sum);
...
pthread_join(tid1, &sum1);

From the thread function you want to send back (with return or pthread_exit()) a pointer.
At pthread_join() you want to obtain this pointer but the result of pthread_join() is an integer to report success/failure.
Then we have to declare a pointer variable (sum1 here) to store the expected result and provide pthread_join() with the address of this variable so that it could be updated (the same way we provide addresses to scanf() in order to update the extracted variables).

like image 184
prog-fh Avatar answered Oct 18 '25 11:10

prog-fh


The problem in your code is the use of casts. In C most of the time a pointer cast signifies an erroneous construct. Notably in this example no casts are required if the constructs are used correctly:

// no cast required because malloc returns void * and void * can be converted
// to a pointer to int without a cast
int *sum = malloc(sizeof (int));

// no cast required because int * can be converted to a void * without a cast
pthread_exit(sum);

void *sum1;

// no cast required because the address of void * is a void **!
pthread_join(tid1, &sum1);

The only place where you require a cast is if you now convert this void * value to int * inline:

int value = *(int *)sum1;

but you can convert it by assignment too, and then again, no cast is required:

int *value_ptr = sum1;
printf("The value was %d\n", *value_ptr);
free(value_ptr);

The rule of thumb is that a cast is OK if you know something better than a compiler - like "truncate this value to uint8_t" or "this void pointer actually points to an int, but I am not assigning it to one to save keystrokes" - but it is usually not OK just to silence a warning.


Some programmers write code like this:

int *ptr;
pthread_join(tid1, (void **)&ptr);

Such code is not strictly conforming as an int * and void * are not compatible types, may have or not have the same representation or even size, and especially may not alias each other.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!