24

While working with Threads in C, I'm facing the warning

"warning: cast to pointer from integer of different size"

The code is as follows

#include<stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<pthread.h>
void *print(void *id)
{
 int a=10;
 printf("My thread id is %ld\n",pthread_self());
 printf("Thread %d is executing\n",id);
 return (void *) 42;
}

int main()
{
 pthread_t th[5];
 int t;
 int i;
 int status;
 void *ret;
 for(i=0;i<5;i++)
 {
   status=pthread_create(&th[i],NULL,print,(void *)i); //Getting warning at this line
   if(status)
   {
    printf("Error creating threads\n");
    exit(0);
   }
   pthread_join(th[i],&ret);
   printf("--->%d\n",(int *)ret);
 }
 pthread_exit(NULL);
}

Can anybody explain how to pass an integer to a function which receives (void * ) as a parameter?

Dinesh
  • 16,014
  • 23
  • 80
  • 122
  • Check `sizeof(int)` and `sizeof(void*)` on your platform. I suspect they're different, which is why you're seeing the warning. – Sean Dec 13 '11 at 10:16
  • @Dinesh: could you please 1) show us those `sizeof`s, I've never seen such a platform, loads of pthread manuals use the code you just showed. 2) accept a different answer, the one you've chosen is just wrong.. – Karoly Horvath Dec 13 '11 at 12:44
  • Please unaccept the answer you have chosen as it is wrong (as the comments below it say) and will lead to bugs. – interjay Oct 22 '13 at 20:56
  • Just want to point out that the purpose of threads is *multitasking*. For example, in a game, you might have a thread, `t`, grabbing the user's input, while the main program does everything else. The game can move on while `t` waits for you to press a key. `t` is like a separate program. They are `asynchronous`. The notion that they speed up your program, however, is a misconception. In fact, threads can actually *slow down* your program. The CPU still has to step through the workload one instruction at a time. Don't use threads in an attempt to gain performance. That is asking for trouble. – Braden Best Sep 29 '15 at 15:05

4 Answers4

44

This is a fine way to pass integers to new pthreads, if that is what you need. You just need to suppress the warning, and this will do it:

#include <stdint.h>

void *threadfunc(void *param)
{
    int id = (intptr_t) param;
    ...
}

int i, r;
r = pthread_create(&thread, NULL, threadfunc, (void *) (intptr_t) i);

Discussion

This may offend your sensibilities, but it's very short and has no race conditions (as you'd have if you used &i). No sense in writing a few dozen lines of extra code just to get a bunch of numbered threads.

Data races

Here is a bad version with a data race:

#include <pthread.h>
#include <stdio.h>

#define N 10

void *thread_func(void *arg)
{
    int *ptr = arg;
    // Has *ptr changed by the time we get here?  Maybe!
    printf("Arg = %d\n", *ptr);
    return NULL;
}

int main()
{
    int i;
    pthread_t threads[N];
    for (i = 0; i < N; i++) {
        // NO NO NO NO this is bad!
        pthread_create(&threads[i], NULL, thread_func, &i);
    }
    for (i = 0; i < N; i++) {
        pthread_join(threads[i], NULL);
    }
    return 0;
}

Now, what happens when I run it with the thread sanitizer?

(Also, check out how it prints "5" twice...)

==================
WARNING: ThreadSanitizer: data race (pid=20494)
  Read of size 4 at 0x7ffc95a834ec by thread T1:
    #0 thread_func /home/depp/test.c:9 (a.out+0x000000000a8c)
    #1 <null> <null> (libtsan.so.0+0x000000023519)

  Previous write of size 4 at 0x7ffc95a834ec by main thread:
    #0 main /home/depp/test.c:17 (a.out+0x000000000b3a)

  Location is stack of main thread.

  Thread T1 (tid=20496, running) created by main thread at:
    #0 pthread_create <null> (libtsan.so.0+0x0000000273d4)
    #1 main /home/depp/test.c:18 (a.out+0x000000000b1c)

SUMMARY: ThreadSanitizer: data race /home/depp/test.c:9 thread_func
==================
Arg = 1
Arg = 2
Arg = 3
Arg = 4
Arg = 5
Arg = 6
Arg = 7
Arg = 8
Arg = 9
Arg = 5
ThreadSanitizer: reported 1 warnings
Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • 1
    +1 absolutely true, but if you take you time to write struct {}, you can save a lot of troubles in the future when you want to receive/send more data then just an int – jackdoe Dec 13 '11 at 10:41
  • 10
    @jackdoe: It's a waste of human life to write code that "you may need in the future". – Dietrich Epp Dec 13 '11 at 10:44
  • 2
    @DietrichEpp can you explain what is race condition with using `(void *)&i` in `pthread_create()`, i am using it and compiler doesn't shows warning,i am thinking but could not figure it out,i am also casting the value passed to the thread like this `int *b=(int*)a` kindly see [this](https://idone.com/MHzoln) – Xax Apr 30 '15 at 15:57
  • 4
    @Xax: First of all, `(void *)` is redundant, just use `&i`. Also, compilers don't warn you about race conditions, you have to figure those out for yourself (or use special tools). The race condition occurs because you have to wait until each thread is done reading `i` before you can change `i` or let it leave scope. Here is an example of what can go wrong: https://gist.github.com/depp/241d6f839b799042c409 – Dietrich Epp Apr 30 '15 at 20:56
  • 1
    @Xax: Here's a fixed version, without the race condition: https://gist.github.com/depp/3f04508a88a114734195 – Dietrich Epp Apr 30 '15 at 21:00
  • @DietrichEpp i [udated link](http://ideone.com/j5VKmj) see the implementation its working .(though ideone donot compile it ) – Xax May 01 '15 at 05:39
  • @DietrichEpp ,i saw your example it quite interesting ,i just use `sleep(1`) to delay thread creation .but why casting to `int` via `intptr_t` solves the race problem. can you xplain a bit – Xax May 01 '15 at 06:00
  • 1
    @Xax: Your implementation has a data race, unfortunately! You cannot test for a data race by running your program, because data races don't *always* cause your program to fail, just *sometimes*. There are actually some other errors in your program: `pthread_t` cannot be printed using `%u`, and you clobber most of your threads (`pthread_t tid`) and only join with the last one. When I ran your program with the thread sanitizer I got errors: see https://gist.github.com/depp/cca2e7c5c664d72ab9ee Now, if you have a question, you should consider the "ask question" button at tho top. – Dietrich Epp May 01 '15 at 06:38
  • @DietrichEpp Thanks for the example, but would be nice if you could point out where the racing problem exactly is. I guess that it is due to the combination of: (1) we pass the reference to `i` which is changing, and (2) in `thread_func()` we create a pointer to refer to `i` (fixed by getting the value directly in your fixed version). – Trần Việt Hoàng Jan 07 '22 at 11:16
0

you can pass the int value as void pointer like (void *)&n where n is integer, and in the function accept void pointer as parameter like void foo(void *n);and finally inside the function convert void pointer to int like, int num = *(int *)n;. this way you won't get any warning.

Rahul
  • 975
  • 9
  • 25
0

you can do something like this:

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <pthread.h>
struct th {
    pthread_t thread;
    int id;
    int ret;
};

void *print(void *id) {
    int a=10;
    struct th *self = (struct th *) id;
    printf("My thread id is %ld\n",pthread_self());
    printf("Thread %d is executing\n",self->id);
    self->ret = random();
    return;
}

int main(void) {
    struct th th[5];
    int t;
    int i;
    int status;
    void *ret;
    for(i=0;i<5;i++) {
        th[i].id = i;
        status=pthread_create(&th[i].thread,NULL,print,&th[i]); //Getting warning at this line
        if(status) {
            printf("Error creating threads\n");
            exit(0);
        }
    }
    for (i=0;i<5;i++) {
        pthread_join(th[i].thread,&ret);
        printf("%d--->%d\n",th[i].id,th[i].ret);

    }
    pthread_exit(NULL);
}

will output:

My thread id is 4496162816
My thread id is 4497870848
My thread id is 4498944000
My thread id is 4498407424
Thread 0 is executing
Thread 1 is executing
My thread id is 4499480576
Thread 3 is executing
Thread 2 is executing
0--->1804289383
Thread 4 is executing
1--->846930886
2--->1714636915
3--->1681692777
4--->1957747793

passing a unique pointer to each thread wont race, and you can get/save any kind of information in the th struct

jackdoe
  • 1,846
  • 1
  • 15
  • 13
-3

change:

status=pthread_create(&th[i],NULL,print,(void *)i);

to:

status=pthread_create(&th[i],NULL,print,(reinterpret_cast<void*>(i));

The reinterpret_cast makes the int the size of a pointer and the warning will stop. Basically its a better version of (void *)i.

user3416126
  • 148
  • 11