【问题标题】:pthread_join:warning: cast from pointer to integer of different size?pthread_join:警告:从指针转换为不同大小的整数?
【发布时间】:2014-01-28 04:44:07
【问题描述】:

我的代码

#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);
}

编译代码时,有两个警告:

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

我看了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.

根据我的理解,exist status(int type)在我的代码中存储到tret,所以我使用(int)void *转换为int,但是上面的警告被抛出了,所以,我的问题是:

如何修改我的代码以清除警告?

【问题讨论】:

  • 因为它警告你的正是你想要做的,你必须忍受它或禁用警告(特定于编译器,可能能够为特定部分做代码)。

标签: c linux pthreads pthread-join


【解决方案1】:

这些警告是无害的(在这种的情况下),可以放心地忽略。

警告来自这些行的演员表:

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

编译器抱怨您将指针(可能是 64 位)向下转换为更小的 32 位整数。由于各种原因,许多遗留的 C 代码喜欢在指针和整数之间来回转换。在过去,指针与整数大小相同,所以这没问题;但是当 64 位目标变得更加普遍时,这突然变得很危险,因为如果您有一个指向地址 0x00000000'ffffffff 上方的 64 位指针,则在将其转换为整数时会丢失高位。当您稍后将其转换回 64 位指针时,您的指针将不正确,并且尝试使用它会崩溃或静默损坏内存。

此处的警告只是试图帮助您避免这些潜在问题。如果指针中的值实际上不是真正的指针,就像在这种情况下,那么如果你知道它的值永远不会超过 0xffffffff,那么将它转换为整数是完全安全的。

有几种方法可以抑制警告。您可以在编译器的命令行中全局禁用它(不推荐);您可以在代码周围使用#pragma 来暂时禁用警告(不可移植);或者,您可以使用一些巧妙的转换来解决它。

有两种数据类型,intptr_tuintptr_t,它们的作用与普通整数一样——您可以向上转换/向下转换为其他整数类型,然后可以进行各种算术运算,等等——但它们re 保证足够大以容纳指针值。在 32 位系统上,intptr_t 将(至少)32 位宽;在 64 位系统上,intptr_t 将(至少)64 位宽。这两种类型的唯一区别是intptr_t 是有符号的,而uintptr_t 是无符号的。

由于编译器知道这些类型总是足够大以容纳指针值,因此当您将指针转换为指向它们或从它们转换为指针时,它不会警告您。一旦进入整数域,您就可以转换为普通的int 而不必担心警告。所以这段代码应该消除你的警告:

#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

【讨论】:

    【解决方案2】:
    #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);
    }
    

    我第一次只删除了警告,没有执行你的代码...

    这是你所有的代码..执行时没有警告:)

    【讨论】:

    • 我之前试过这个,Segment Fault 被扔掉了。函数pthread_join的返回值不是存储在*tret中,而是存储在tret中。
    • 现在检查 .. 第一次我只干了没有执行 :) @Charles0429
    【解决方案3】:

    试试这个应该没问题

    作为 thread_join 的定义,它期望 void ** 不是 void 指针

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

    并在它返回值后对其进行延迟

    printf("thread 1 return code:%d\n", *(int *)tret);
    

    【讨论】:

    • &amp;tret 已经是 void** 类型,强制转换完全没有意义。并且取消引用tret 肯定会崩溃,因为地址1 不是有效的指针值。
    猜你喜欢
    • 2012-11-12
    • 1970-01-01
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 2019-08-13
    相关资源
    最近更新 更多