【问题标题】:C: How to dereference void**?C:如何取消引用 void**?
【发布时间】:2014-07-23 00:01:04
【问题描述】:

考虑以下代码:

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));
这导致了一个错误:
错误:一元‘*’的无效类型参数(有‘int’)
还有这个:
printf("thread finished and returned %d\n", *(int*)(*ret));
这也导致了错误(和警告):
警告:取消引用‘void *’指针[默认启用]
错误:无效使用无效表达式

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

【问题讨论】:

  • 代码正在取消引用不允许访问的内存。也许printf("thread finished and returned %p\n", ret); 打印指针。

标签: c pthreads


【解决方案1】:

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

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

  • 如果您在指针中返回 int,您可以先将其转换为 uintptr_t,然后再转换为 void*,然后按相反的顺序返回 int,或者
  • 如果您希望在 main 中取消引用,则需要将您的 int 放入内存中,并传回指向该内存的指针,以便可以在 main 中取消引用。

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

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

请记住包含 &lt;stdint.h&gt; 以使用 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 方法更难。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-17
    • 2014-04-29
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多