Consider the following code:
void* run(void* arg) {
int* array=(int*)arg;
printf("In run!\n");
int i;
for (i=0; i<10; i++) {
printf("%d ",array[i]);
}
printf("\n");
return (void*)15;
}
int main() {
pthread_t my_thread;
int array[10]={0};
void* ret;
int i;
for (i=0; i<10; i++) {
array[i]=i+1;
}
if (pthread_create(&my_thread, NULL, run, (void*)array)!=0) {
perror("thread creation failed");
return 1;
}
pthread_join(my_thread, &ret);
printf("thread finished and returned %d\n", *(int*)ret); // segfault. why??
return 0;
}
I'm trying to obtain the value 15, returned by the thread that was created, but for some reason, that last printf throws segmentation fault.
What is the reason for the segmentation fault, and what is the right way to obtain the returned value 15?
I also tried this:
printf("thread finished and returned %d\n", *(*(int*)ret));
Which resulted in an error:
error: invalid type argument of unary ‘*’ (have ‘int’)
and this:
printf("thread finished and returned %d\n", *(int*)(*ret));
which also resulted in an error (and a warning):
warning: dereferencing ‘void *’ pointer [enabled by default]
error: invalid use of void expression
What is the right way to do it, and most importantly, what is the reason for that segfault?
The reason for the failure is that your thread returns an integer in place of a void*, and the code in main tries to dereference it.
It is illegal to do both these things at once, but you can do each one of them separately:
If you are returning an int in a pointer, you could cast it to uintptr_t before casting to void*, and do the sequence in reverse to get back an int, or
If you wish to dereference in the main, you need to put your int in memory, and pass back a pointer to that memory so that it could be dereferenced in main.
I would use the first approach, like this:
// Inside run():
return (void*)((uintptr_t)15);
// Inside main():
printf("thread finished and returned %d\n", (int)((uintptr_t)ret));
Remember to include <stdint.h> in order to use the uintptr_t type.
Using the second approach is a bit trickier:
// Inside run():
int *ret = malloc(sizeof(int)); // You need to use dynamic allocation here
*ret = 15;
return ret;
// Inside main():
int *run_ret = ret;
printf("thread finished and returned %d\n", *run_ret);
free(run_ret); // You need to free malloc-ed memory to avoid a leak
You could potentially simplify it by allocating the buffer for the result in the caller, but either way that is going to be harder than using the uintptr_t approach.
Related
I originally had a global variable for my fibonacci variable array, but found out that is not allowed. I need to do elementary multithreading and handle race conditions, but I can't get past feeding an int as a void argument in pthread create. I've tried using a constant pointer with no luck. For some strange reason the void* gets past the first boolean test but not the else if:
$ gcc -o fibonacci fibonacci.c
fibonacci.c:22:16: warning: comparison between pointer and integer ('void *' and 'int')
else if (arg == 1)
~~~ ^ ~
1 warning generated.
My code is a mess and I am getting really confused because I have rewritten it so many times. If I cast all the args in my thread run function as ints I get a segmentation fault 11, which makes sense. All attempts at passing the i index by address and dereferencing it have failed, as it is a void and can't be used as an int. Can you suggest something else?
#include<stdio.h> //for printf
#include<stdlib.h> //for malloc
#include<pthread.h> //for threading
#define SIZE 25 //number of fibonaccis to be computed
int *fibResults; //array to store fibonacci results
void *run(void *arg) //executes and exits each thread
{
if (arg == 0)
{
fibResults[(int)arg] = 0;
printf("The fibonacci of %d= %d\n", (int)arg, fibResults[(int)arg]);
pthread_exit(0);
}
else if (arg == 1)
{
fibResults[(int)arg] = 1;
printf("The fibonacci of %d= %d\n", (int)arg, fibResults[(int)arg]);
pthread_exit(0);
}
else
{
fibResults[(int)arg] = fibResults[(int)arg -1] + fibResults[(int)arg -2];
printf("The fibonacci of %d= %d\n", (int)arg, fibResults[(int)arg]);
pthread_exit(0);
}
}
//main function that drives the program.
int main()
{
pthread_attr_t a;
fibResults = (int*)malloc (SIZE * sizeof(int));
pthread_attr_init(&a);
for (int i = 0; i < SIZE; i++)
{
pthread_t thread;
pthread_create(&thread, &a, run,(void*) &i);
printf("Thread[%d] created\t", i);
fflush(stdout);
pthread_join(thread, NULL);
printf("Thread[%d] joined & exited\t", i);
}
return 0;
}
You don't need the cast in the call to pthread_create() — the conversion to void * is automatic.
In the thread function, you could use
int i = *(int *)arg;
However, you've now got a synchronization problem; all the threads are using the same (pointer to the same) integer variable, and you can't predict which value they're going to see because of scheduling issues. The per-thread data needs to be 'per thread'.
So, there are various ways around that. In this context, I'd probably use
#include <stdint.h>
and in main():
pthread_create(&thread, &a, run, (void*)(uintptr_t)i);
and then in the thread function:
int i = (uintptr_t)arg;
Now the casts — the double cast even — is necessary. The cast to uintptr_t ensures the integer value is big enough to hold a pointer; the cast to void * is needed because there isn't an implicit cast from any integer type to void *. This ensures each thread function invocation has a different value. Sharing a pointer to an int means that everything is uncontrolled.
In the run() function you should do:
void *run(void *ptrarg) //executes and exits each thread
{
int arg = *((int *)ptrarg);
if (arg == 0)
....
....
and in rest of the run(), you don't need to cast the arg. Replace (int)arg with arg.
EDIT:
The way you are passing the argument to fun() while creating threads may cause race condition because all threads will be using same pointer. Check the #Jonathan's answer to avoid this problem.
#efuddy. Instead of (int)arg you should use (int *)arg to properly cast the **void pointer* void *arg
I got some strange behavior of my code.
I can`t pass a structure to the callback function.
#include <malloc.h>
#include "stdint.h"
typedef struct {
int test_rssi;
int setup_rssi;
} test_setup_scan_result;
typedef void (*WifiCallback)(uint8_t);
WifiCallback TestSetupCb;
void resume_configuration(test_setup_scan_result *result) {
if (result == NULL) {
printf("result is NULL\n");
return;
}
printf("result is not NULL\n");
printf("setup_rssi %d\n", result->setup_rssi);
printf("test_rssi %d\n", result->test_rssi);
printf("done");
}
void scan_test_setup_done_cb() {
printf("scan_done\n");
test_setup_scan_result *scan_result = malloc(sizeof(test_setup_scan_result));
printf("created structure\n");
scan_result->test_rssi = 1;
scan_result->setup_rssi = 1;
printf("filled structure\n");
if (TestSetupCb) {
printf("executing cb\n");
printf("setup_rssi %d\n", scan_result->setup_rssi);
printf("test_rssi %d\n", scan_result->test_rssi);
TestSetupCb((uint8_t) scan_result);
}
}
void scan_for_test_setup(WifiCallback cb) {
TestSetupCb = cb;
scan_test_setup_done_cb();
}
int main(void) {
printf("Hello World\n");
scan_for_test_setup((WifiCallback)resume_configuration);
return 0;
}
The code after I am trying to get values of the structure in resume_configuration function just not works. I am the newbie in c language so any links to useful articles are regarded.
Casting a function name to a function pointer type with incompatible parameter types is undefined behavior:
scan_for_test_setup((WifiCallback)resume_configuration);
// ^^^^^^^^^^^^^^
// Undefined behavior
This by itself is enough to get a crash. However, your program does another thing illegally - the call below
TestSetupCb((uint8_t) scan_result);
// ^^^^^^^^^^^
// Does not fit in uint8_t
would fail regardless of the function pointer cast, because a pointer does not fit in 8 bits.
The variable “scan_result” is pointer to struct with allocated memory space in heap region.
When the TestSetupCb() is called with argument “(uint8_t) scan_result” you actually casting address of “scan_result” to be uint8_t, which means to take a first byte of the address and pass it by value. In that case you lose data that you want process in resume_configuration() function.
For example: let’s say the “scan_result” struct it at address “0x004EE388” when you casting this address to uint8_t the result is “0x00000088” this address is invalid and creates issue in your program. Also, this kind of operation creates dangerous to your program.
To solve your problem just re-define function pointer in the following way:
typedef void(*WifiCallback)( test_setup_scan_result *);
and update your code: instead of TestSetupCb((uint8_t)scan_result); change to TestSetupCb(scan_result);
I have run it in Valgrind and I have identified a blatant error (which manifests in several places):
resume_configuration does not obey the WifiCallback pointer type; it takes a parameter of pointer type, not of uint8_t type which most likely has a different size (and it indeed has)
You call TestSetupCb((uint8_t) scan_result); -- you explicitly convert the scan_result pointer to a datatype smaller than a pointer. You have truncated a pointer, so now the result cannot be converted back into a valid pointer. The truncation on Intel systems is so bad, any resulting pointer will always be in the NULL page.
I wrote this small program for understanding pthread_create and pthread_join but I dont understand why the value of the variable data gets altered after thread_join. Its printed as 0 after the call to pthread functions.
#include <pthread.h>
#include <stdio.h>
void* compute_prime (void* arg)
{
int n = *((int*) arg);
printf("Argument passed is %d\n",n);
return (void *)n;
}
int main ()
{
pthread_t thread;
int data = 5000;
int value=0;
pthread_create (&thread, NULL, &compute_prime, &data);
pthread_join (thread, (void*) &value);
printf("The number is %d and return value is %d.\n", data, value);
return 0;
}
And the output is
Argument passed is 5000
The number is 0 and return value is 5000.
This is because pthread_join has the prototype void **. It expects a pointer to an object of type void *; it modifies this void * object. Now it so happens that you're running on a 64-bit arch, where data and value are both 32 bits, and laid out in memory sequentially. Modifying a void * object that is laid out in memory starting from the address of the int object value clobbers the int object data too, as these are both 32 bits - thus you will see that the data was overwritten. However, this is undefined behaviour so anything might happen.
Don't use casts as they will only serve to hide problems. Casting to a void * is especially dangerous as a void * can be converted to any other type implicitly, even to void **, even though usually it too would be incorrect. If you remove the cast, you most probably will get a warning or an error like
thrtest.c: In function ‘main’:
thrtest.c:16:31: error: passing argument 2 of ‘pthread_join’ from
incompatible pointer type [-Werror=incompatible-pointer-types]
pthread_join (thread, &value);
if compiling with warnings enabled.
If however you really want to do this, you must do it like this:
void *value;
pthread_join(thread, &value);
intptr_t value_as_int = (intptr_t)value;
Though it is not really portable either, as the conversion is implementation-defined.
The most portable way to return an integer is to return a pointer to a mallocated object:
int *return_value = malloc(sizeof (int));
*return_value = 42;
return return_value;
...
void *value;
pthread_join(thread, &value);
int actual = *(int *)value;
free(value);
Hi guys I'm having trouble with this code
int file_id;
void* wraper(void* p){
return (void)reader((int)p);
}
int main(int argc, char *argv[]){
srandom ((unsigned) time(NULL));
int i;
pthread_t tid[3];
for(i=0;i<3;i++){
pthread_t * temp = malloc(sizeof(tid[i]));
file_id=get_random(NB_FILES);
pthread_create(&tid[i], NULL,wraper,(void*)file_id);
}
and the compiler is giving me this
reader-thread.c: In function ‘wraper’:
reader-thread.c:59:25: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
return (void)reader((int)p);
^
reader-thread.c:59:5: error: void value not ignored as it ought to be
return (void)reader((int)p);
^
reader-thread.c: In function ‘main’:
reader-thread.c:70:46: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
pthread_create(&tid[i], NULL,wraper,(void*)file_id);
^
The objective is to create 3 threads and send them the file_id to the function reader, I can't see what I'm doing wrong
Your compiler is correct, you shouldn't ignore this, on many architectures pointers and int don't have the same width. The correct type, if you really have to, is to use uintptr_t or intptr_t.
Also casting the return of the function (that you didn't show us) to (void) makes no sense if you have to return a void*.
Casting the other way around from int to void* is almost as bad as 1.
In essence you shouldn't try to violate the call interface for thread functions. If you have to transmit data, pass a pointer to the data.
Also, please, when you post a question here, be sure that the error messages correspond to the code that you posted.
I want to write a multi threaded program in c language. I use posix thread library.
I write the following code:
#include<stdio.h>
#include<pthread.h>
void *put (int *arg)
{
int i;
//int * p;
// p=(int*)arg;
for(i=0;i<5;i++)
{
printf("\n%d",arg[i]);
}
pthread_exit(NULL);
}
int main()
{
int a[5]={10,20,30,40,50};
pthread_t s;
pthread_create(&s,NULL,put,a);
printf("what is this\n");
return 0;
}
I just want my thread just show the items in the array. The program compiled with following warning:
tm.c:19: warning: passing argument 3 of ‘pthread_create’ from incompatible pointer type
/usr/include/pthread.h:227: note: expected ‘void * (*)(void *)’ but argument is of type ‘void * (*)(int *)’
When I run the program I got the out put of main thread but not the value stored in array.
Now can anyone tell me what I'm doing wrong?
How to send the array as an argument in the thread function?
If I just changed the code little bit the compile time warning resolved the changed code is following:
#include<stdio.h>
#include<pthread.h>
void *put (void *arg)
{
int i;
int * p;
p=(int*)arg;
for(i=0;i<5;i++)
{
printf("\n%d",p[i]);
}
pthread_exit(NULL);
}
int main()
{
int a[5]={10,20,30,40,50};
pthread_t s;
pthread_create(&s,NULL,put,a);
printf("what is this\n");
return 0;
}
But the output does not change. Can any one tell me what i did wrong? What is the proper way to send array to a thread function (put in this case)?
Your code creates the thread and then the process exits by reaching the end of main. You have to wait for the thread to have a chance to execute, by calling pthread_join, or sleeping for a bit.
First of all, you need to wait for the thread to finish before returning from main().
Another problem with this code is that the array a is allocated on the stack of the main() routine and is thus potentially invalid in the context of a different thread. You should heap allocate a with a call to malloc().
If you wait for the thread to finish in main() then a is probably valid since the stack frame for main() will still exist. However, any future refactorings are liable to cause you grief so please switch to using malloc().
Try to wait for your thread to execute, add
pthread_join(s, NULL);
before your return 0;