Pregunta

My code

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

void * thread_func1(void *args)
{
    printf("thread 1 returning\n");
    return ((void *)1);
}

void * thread_func2(void *args)
{
    printf("thread 2 exiting\n");
    pthread_exit((void *)2);
}

int main(void)
{
    int err;
    pthread_t tid1, tid2;
    void *tret;

    err = pthread_create(&tid1, NULL, thread_func1, NULL);
    if(err)
    {
        printf("cannot create thread 1\n");
    }
    err = pthread_create(&tid2, NULL, thread_func2, NULL);
    if(err)
    {
        printf("cannot create thread 2\n");
    }

    err = pthread_join(tid1, &tret);
    if(err)
    {
        printf("thread 1 join error\n");
    }
    printf("thread 1 return code:%d\n", (int)tret);

    err = pthread_join(tid2, &tret);
    if(err)
    {
        printf("cannot join thread 2\n");
    }
    printf("thread 2 return code:%d\n", (int)tret);
    exit(0);
}

when compling the code, there're two warnings:

join.c:44: warning: cast from pointer to integer of different size
join.c:51: warning: cast from pointer to integer of different size

I read the man page of pthread_join:

 int pthread_join(pthread_t thread, void **retval);
   If retval is not NULL, then pthread_join() copies the exit status of
   the target thread (i.e., the value that the target thread supplied to
   pthread_exit(3)) into the location pointed to by *retval.  If the
   target thread was canceled, then PTHREAD_CANCELED is placed in
   *retval.

According to my understanding, the exist status(int type) is stored into tret in my code, so I use (int) to convert void * to int, but the above warnings are thrown out, So, my question is:

How to modify my code to clear up the warnings?

¿Fue útil?

Solución

These warnings are harmless (in this case) and can safely be ignored.

The warnings are coming from the casts on these lines:

printf("thread 1 return code:%d\n", (int)tret);  // line 44
...
printf("thread 2 return code:%d\n", (int)tret);  // line 51

The compiler is complaining that you're casting a pointer (which may be 64 bits) down into a smaller, 32-bit integer. A lot of legacy C code likes to cast back-and-forth between pointers and integers for various reasons. In the old days, pointers were the same size as integers, so this was ok; but when 64-bit targets became more common, this is dangerous all of a sudden, since if you have a 64-bit pointer pointing above the address 0x00000000'ffffffff, you'll lose the upper bits when casting it to an integer. When you cast that back to a 64-bit pointer later, your pointer will be incorrect, and attempting to use it will crash or silently corrupt memory.

The warnings here are just trying to help you avoid these potential problems. If the value in your pointer isn't actually a real pointer, like in this case, then it's perfectly safe to cast it down to an integer if you know its value is never going to exceed 0xffffffff.

There are a few ways to suppress the warning. You could disable it globally in your compiler's command line (not recommended); you could use a #pragma around the code to temporarily disable the warning (not portable); or, you could use some clever casting to work around it.

There are two data types, intptr_t and uintptr_t, which act just like ordinary integers—you can upcast/downcast to other integer types, you can do all sorts of arithmetic on then, etc.—but they're guaranteed to be large enough to hold a pointer value. On a 32-bit system, intptr_t will be (at least) 32 bits wide; on a 64-bit system, intptr_t will be (at least) 64 bits wide. The only difference between the two types is that intptr_t is signed while uintptr_t is unsigned.

Since the compiler knows that these types are always large enough to hold pointer values, it won't warn you when you cast a pointer to or from them. Once you get into the integer domain, you can then cast to an ordinary int without fear of warnings. So this code should eliminate your warnings:

#include <stdint.h>
...
printf("thread 1 return code:%d\n", (int)(intptr_t)tret);  // line 44
printf("thread 2 return code:%d\n", (int)(intptr_t)tret);  // line 51

Otros consejos

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void * thread_func1(void *args)
{
    printf("thread 1 returning\n");
    return ((void *)1);
}

void * thread_func2(void *args)
{
    printf("thread 2 exiting\n");
    pthread_exit((void *)2);
}

int main(void)
{
    int err;
    pthread_t tid1, tid2;
    int *tret = malloc(sizeof(int)); 

    err = pthread_create(&tid1, NULL, &thread_func1, NULL);
    if(err)
    {
        printf("cannot create thread 1\n");
    }
    err = pthread_create(&tid2, NULL, &thread_func2, NULL);
    if(err)
    {
        printf("cannot create thread 2\n");
    }

    err = pthread_join(tid1, (void *)tret);
    if(err)
    {
        printf("thread 1 join error\n");
    }
    printf("thread 1 return code:%d\n", *(tret));

    err = pthread_join(tid2, (void *)tret);
    if(err)
    {
        printf("cannot join thread 2\n");
    }
    printf("thread 2 return code:%d\n", *(tret));
    exit(0);
}

First Time I Only Removed Warning, Not executed your code...

This is your all code .. with execution without warning :)

Try this it should work fine

As the defintion of thread_join it expects void ** not a void pointer

err = pthread_join(tid1, (Void **)&tret);

and for deferencing it after it returns the value

printf("thread 1 return code:%d\n", *(int *)tret);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top