I'm learning threading in C in OS. I don't know why following code is giving me segmentation fault. Can anyone help me here? I am also confused a bit about how pthread_join uses its argument void ** retval. What is its function?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void *thread (void *vargp) {
int* arg = *((int*)vargp);
return (void*)arg;
}
int main () {
pthread_t tid;
int thread_arg = 0xDEADBEEF;
int *ret_value;
pthread_create(&tid, NULL, thread, &thread_arg);
pthread_join(tid, (void **)(&ret_value));
printf("%X\n", *ret_value);
return 0;
}
This is not correct:
int* arg = *((int*)vargp);
(int*)vargp cast your void* to int*. But by writing int* arg = *((int*)vargp); you assing to the arg pointer the VALUE (0xDEADBEEF) of the argument vargp. This value (0xDEADBEEF) is not a valid adress.
what is the version of your compiler? because he must alert you :
invalid conversion from int to int*
You should write:
int* arg = (int*) vargp;
Related
I'm trying to pass pointers to struct lower_hyper_id from a thread to the main thread, by the means of pthread_exit() function, that would compare and output the value in the struct. However, i receive an error (Segmentation fault) when i am trying to use the returned value and cast it to the struct.
thread that creates and returns the struct:
void *compute(void *arg){
lower_hyper_id *data = (lower_hyper_id *)malloc(sizeof(lower_hyper_id));
//some code
//i debug the program, and at this point, the struct i want
//to return has the values i want.
pthread_exit((void *)data);
}
in the main:
lower_hyper_id l_hyper_id;
int main(){
void *ap_state;
lower_hyper_id values;
void *ret;
//some code
for (int i = 0; i < NUMBER_OF_FILTERING_THREADS; i++)
{
s = pthread_join(filtering_threads[i], (void *)&ret);
//some error checking
values = *((lower_hyper_id *)ret); //this is where i receive the error
if (values.lowest_cost <= l_hyper_id.lowest_cost)
{
l_hyper_id.hyper_id = values.hyper_id;
l_hyper_id.lowest_cost = values.lowest_cost;
}
free(ret);
}
I have already looked at answers in the stackoverflow such as this question, but it hasn't helped me resolving this. I actually changed the code to be exactly equal to the code in this answer, but still it gives me an error.
You're not testing if malloc returned NULL. That could be an issue if you're allocing a large chunk and the allocation can fail.
Other than that, I don't think the problem is in the return value passing.
pthread_exit()ing with a mallocd pointer should work just fine.
A minimial working example:
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *compute (void *arg)
{
printf("thread=%llx\n", (unsigned long long)pthread_self());
size_t sz = strlen("hello world")+1;
char *ret = malloc(sz+1);
if(ret) memcpy(ret, "hello world", sz+1);
return ret;
}
int main()
{
printf("thread=%llx\n", (unsigned long long)pthread_self());
pthread_t ptid;
int er;
if((er=pthread_create(&ptid,0,compute,0))) return errno=er,perror(0),1;
void *retval;
if((er=pthread_join(ptid,&retval))) return errno=er,perror(0),1;
printf("thread returned: %s\n", (char*)retval);
free(retval);
}
I have a problem with my project which is supposed to add up every line using a thread then sum it all, but I'm getting an error that says lvalue required as unary '&" operand
pthread_create(&tid, NULL, &sum_line(0), NULL);
I've tried some thing but couldn't solve it, any ideas? Thanks
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
static void * sum_line(int nr_line);
int Sum;
int A[4][4];
int main() {
pthread_t tid;
Sum=0;
printf("\nOrig thread tid(%d) Sum=%d", pthread_self(), Sum);
pthread_create(&tid, NULL, &sum_line(0), NULL);
printf("\nChild thread was created tid(%d)", tid);
pthread_join(tid,NULL);
printf("\nOrig thread tid(%d)-->Child thread ended tid(%d) Sum=%d",pthread_self(), tid, Sum);
printf("\n");
}
static void * sum_line(int nr_line) {
int i;
for(i=0;i<4;i++) {
Sum=Sum+A[i];
printf("\nChild thread tid(%d), i=%d, Sum=%d",pthread_self(),i,Sum);
sleep(2);
}
printf("\nChild thread tid(%d)--> ending", pthread_self());
}
Pass a pointer to function to pthread_create()
Write just sum_line, not &sum_line(0).
The pthread_create() function expects a pointer to the thread function — i.e. the function name — and not the result of calling the function. The pthread_create() function will arrange for the new thread to call the function, but it needs a function pointer.
Also, the signature for a thread function must be:
void *function(void *arg);
The function should also return a value — add return 0; before the close brace.
You pass a null pointer to the function; you can't expect that to work as int nr_line. You'll need to do some fancy footwork to get a number to the function.
There are two main options:
Either
int nr_line = 247;
pthread_create(&tid, NULL, sum_line, &nr_line);
The function then looks like:
void *sum_line(void *arg)
{
int nr_line = *(int *)arg;
…
return 0;
}
Just make sure each thread gets a pointer to a different object when you start multiple threads.
Or
uintptr_t nr_line = 247;
pthread_create(&tid, NULL, sum_line, (void *)nr_line);
Or:
int nr_line = 247;
pthread_create(&tid, NULL, sum_line, (void *)(uintptr_t)nr_line);
and the function then looks like:
void *sum_line(void *arg)
{
int nr_line = (uintptr_t)arg;
…
return 0;
}
The double cast avoids compiler warnings about converting an integer of a different size to a pointer.
Note that pthread_create() will call the function as if it is void *function(void *args), so passing it any other type of function pointer, even if cast with (void (*)(void *)), is cheating and leads to undefined behaviour.
this is the right use of pthread_create with no warning:
#include <pthread.h>
#include <stdio.h>
void *check(void *temp) {
int* i = (int *)temp;
printf("%d\n", *i);
}
int main(void) {
pthread_t check_thread;
int i = 1;
pthread_create(&check_thread, NULL, check , (void *)&i);
pthread_join(check_thread, NULL);
return 0;
}
but the following code can also run well, just change void *check to void check:
#include <pthread.h>
#include <stdio.h>
void check(void *temp) {
int* i = (int *)temp;
printf("%d\n", *i);
}
int main(void) {
pthread_t check_thread;
int i = 1;
pthread_create(&check_thread, NULL, check, (void *)&i);
pthread_join(check_thread, NULL);
return 0;
}
if i change check to &check, it can also run well
#include <pthread.h>
#include <stdio.h>
void check(void *temp) {
int* i = (int *)temp;
printf("%d\n", *i);
}
int main(void) {
pthread_t check_thread;
int i = 1;
pthread_create(&check_thread, NULL, &check, (void *)&i);
pthread_join(check_thread, NULL);
return 0;
}
i see the thrid argument of pthread_create is: void *(*start_routine) (void *)
can someone tell me what does it mean?
Per the POSIX standard for pthread_create():
SYNOPSIS
#include <pthread.h>
int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void*), void *restrict arg);
That means that the third argument to pthread_create() must be a function pointer of the form void *(*start_routine)(void*). The function pointer passed must refer to a function
declared and defined as
void *start_routine( void *arg )
{
void *ptr = ...;
...
return( ptr );
}
Period. End of discussion. Full stop.
You are invoking undefined behavior by not passing a function of the type void *(*start_routine) (void *) as the third argument to pthread_create().
Per J.2 Undefined behavior, paragraph 1 of the C standard:
The behavior is undefined in the following circumstances:
...
A pointer is used to call a function whose type is not compatible with the referenced type.
"Works with no observed issue" is covered by "undefined behavior". "Program crashes" is also covered.
The deal of the C standard is to write portable code, that could run on any conforming platform. The fact that this runs on your platform without visible errors, does not mean that it would on other platforms. Reasons for failure could e.g be that pthread_join could try to access a hardware register with the return value.
It is nothing but a function pointer. Lets break it down.
void *(*start_routine) (void *)
void* -> return type of function
start_routine -> function pointer name
void* -> argument type
the address of the function you pass will be assigned to function pointer start_routine and start_routine will be invoked as new thread from kernel.
I'm trying to edit this code to work with ints parameters:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
void* worker (void* param) {
int* nr = (int *) param;
printf ("I got: %d\n",nr);
}
int main (int argc, int *argv[])
{
pthread_t th;
int i;
for(i=1;i<argc;i++){
pthread_create (&th, NULL, worker,(void*)argv[i]);
pthread_join (th, NULL);
}
}
This is not working, smth about pointers, I don't understand. Can anyone explain me? I don't want to use "atoi" function.
For number 5 and 2 I get: -1078000975,-1078000973 and a warning:
11:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf ("I got: %d\n", nr);
^
A few issues:
argv should be written char * argv[], not int * argv[].
Your (void *) cast in your pthread_create() call is unnecessary.
Your thread function should return a void *.
atoi(), or its more capable cousin, strtol(), is exactly what you're looking for, here. You can either use them, or convert your strings manually, which is suboptimal.
Here's a working version:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void * worker (void * param)
{
char * numstr = param, * endptr;
long num = strtol(numstr, &endptr, 0);
if ( *endptr ) {
printf("Invalid number.\n");
}
else {
printf ("I got: %ld\n", num);
}
return NULL;
}
int main (int argc, char *argv[])
{
pthread_t th;
for ( int i = 1; i < argc; ++i ) {
pthread_create (&th, NULL, worker, argv[i]);
pthread_join (th, NULL);
}
return 0;
}
and some sample output:
paul#horus:~/src/sandbox$ ./trd 5 haha 10
I got: 5
Invalid number.
I got: 10
paul#horus:~/src/sandbox$
If the arguments you recieve are smaller than 10, you can do this:
pthread_create (&th, NULL, worker,(void*)(argv[i][0]-'0'));
This can be done because ASCII numbers begin at 48 ('0' value). So if you receive a '7' (55 ascii number), you can subtract the '0' to get it: 55-48=7.
If the arguments can be 10 or greater, you must use atoi or a self-implementation of that function, as you can not cast from char* to int in C.
There is another problem with your code, you try to print an int*, which is only a variable that contains a memory address. You should recieve it as an int:
void* worker (void* param)
{
int nr = (int) param;
printf ("I got: %d\n",nr);
}
EDIT:
So your code should look like this:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
void* worker (void* param) {
int nr = (int) param;
printf ("I got: %d\n",nr);
}
int main (int argc, char *argv[])
{
pthread_t th;
int i;
for(i=1;i<argc;i++){
pthread_create (&th, NULL, worker,(void*)(argv[i][0]-'0'));
pthread_join (th, NULL);
}
}
It works for me...
You should pass the pointer to the string and then manipulate it.
pthread_create (&th, NULL, worker, argv[i]); //cast is not required
void* worker (void* param) {
char* nr = param ;
Now you got your string in the thread. Get the first character, and convert it to an integer.
int n = nr[0]-'0' ;
printf ("I got: %d\n",n);
}
I have the following functions :
void *foo(void *i) {
int a = (int) i;
}
int main() {
pthread_t thread;
int i;
pthread_create(&thread, 0, foo, (void *) i);
}
At compilation, there are some errors about casting ((void *) i and int a = (int) i). How can I pass an integer as the last argument of pthread_create properly?
Building on szx's answer (so give him the credit), here's how it would work in your for loop:
void *foo(void *i) {
int a = *((int *) i);
free(i);
}
int main() {
pthread_t thread;
for ( int i = 0; i < 10; ++1 ) {
int *arg = malloc(sizeof(*arg));
if ( arg == NULL ) {
fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
exit(EXIT_FAILURE);
}
*arg = i;
pthread_create(&thread, 0, foo, arg);
}
/* Wait for threads, etc */
return 0;
}
On each iteration of the loop, you're allocating new memory, each with a different address, so the thing that gets passed to pthread_create() on each iteration is different, so none of your threads ends up trying to access the same memory and you don't get any thread safety issues in the way that you would if you just passed the address of i. In this case, you could also set up an array and pass the addresses of the elements.
You can allocate an int on the heap and pass it to pthread_create(). You can then deallocate it in your thread function:
void *foo(void *i) {
int a = *((int *) i);
free(i);
}
int main() {
pthread_t thread;
int *i = malloc(sizeof(*i));
pthread_create(&thread, 0, foo, (void *) i);
}
You should cast the address of i (rather than the value of i as you do now) in the last argument of pthread_create().
pthread_create(&thread, 0, foo, (void *) &i);
^ is missing
And the casting is wrong in your function too. It should be:
int a = *((int*) i);
If you intend to read the value, you should also initialize i to some value in main() as it's uninitialized now.
2 Use proper definition for main():
int main(void)
or int main(int argc, char *argv[]) or its equivalent.
Old question, but I faced the same problem today, and I decided not to follow this path.
My application was really about performance, so I chose to have this array of ints declared statically.
Since I don't know a lot of applications where your pthread_join / pthread_cancel is in another scope than your pthread_create, I chose this way :
#define NB_THREADS 4
void *job(void *_i) {
unsigned int i = *((unsigned int *) _i);
}
int main () {
unsigned int ints[NB_THREADS];
pthread_t threads[NB_THREADS];
for (unsigned int i = 0; i < NB_THREADS; ++i) {
ints[i] = i;
pthread_create(&threads[i], NULL, job, &ints[i]);
}
}
I find it more elegant, more efficient, and you don't have to worry about freeing since it only lives in this scope.
While this is an old question there is one option missing when all you need is to pass a positive integer like a descriptor: you can pass it directly as the address, while it it a hack it works well and avoid allocating anything :)
NOTE: the size of the integer must match the size of a pointer on your OS but nowadays most systems are native 64bits.
#include <pthread.h>
#include <inttypes.h>
#include <stdio.h>
void *_thread_loop(void *p)
{
uint64_t n = (uint64_t)p;
printf("received %llu\n", n);
return NULL;
}
int main(int argc, char const *argv[])
{
pthread_t read_thread_id;
uint64_t n = 42;
pthread_create(&read_thread_id, NULL, _thread_loop, (void *)n);
pthread_join(read_thread_id, NULL);
return 0;
}