首页 文章

C:如何取消引用无效**?

提问于
浏览
1

请考虑以下代码:

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;

}

我正在尝试获取由创建的线程返回的值15,但由于某种原因,最后一个printf会引发分段错误 .
分段错误的原因是什么,获取返回值15的正确方法是什么?
我也试过这个:
printf("thread finished and returned %d\n", *(*(int*)ret));
这导致了一个错误:
error: invalid type argument of unary ‘*’ (have ‘int’)
还有这个:
printf("thread finished and returned %d\n", *(int*)(*ret));
这也导致了错误(和警告):
*warning: dereferencing ‘void ’ pointer [enabled by default] error: invalid use of void expression

什么是正确的方法,最重要的是,这个段错误的原因是什么?

1 回答

  • 4

    失败的原因是你的线程返回一个整数代替 void* ,而 main 中的代码试图取消引用它 .

    同时做这两件事是违法的,但你可以分别做到这两件事:

    • 如果在指针中返回 int ,可以在转换为 void* 之前将其强制转换为uintptr_t,然后反向执行序列以返回 int ,或者

    • 如果你想在 main 中取消引用,你需要将 int 放在内存中,然后传回指向该内存的指针,以便在 main 中取消引用它 .

    我会使用第一种方法,如下所示:

    // Inside run():
    return (void*)((uintptr_t)15);
    // Inside main():
    printf("thread finished and returned %d\n", (int)((uintptr_t)ret));
    

    请记住包含 <stdint.h> 以使用 uintptr_t 类型 .

    使用第二种方法有点棘手:

    // 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
    

    您可以通过在调用者中为结果分配缓冲区来简化它,但这种方式比使用 uintptr_t 方法更难 .

相关问题