pthread_join()导致崩溃后指向int的指针

时间:2018-05-21 03:09:04

标签: c pthreads

在修补pthread时,我遇到了一个令人困惑的问题。

如果我在 pthread_join之后定义了一个int指针,它似乎会使程序崩溃。在pthread_join之前的任何地方,它都可以正常工作。我想知道为什么会这样。

works.c

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

void *somefunction(void *vargp);


int main(int argc, char **argv){
    if (argc < 2){
        fprintf(stderr, "Invalid usage, bleh\n");
        return 1;
    }
    int argu = atoi(argv[1]);
    pthread_t tid;
    int rc = pthread_create(&tid, NULL, somefunction, &argu);
    assert (rc == 0);
    void **retval;
    int foo = 10;
    int *foo_ptr = &foo;
    pthread_join(tid, retval);
    printf("retval is %d\n", **(int **)retval);

    printf("*foo_ptr is %d\n", *foo_ptr );


    pthread_exit(NULL);
}


void *somefunction(void *vargp){
    int *someint = (int *) vargp ;
    *someint = *someint * 3;
    printf("In somefunction, someint value is %d\n", *someint);
    pthread_exit(someint);
}

failed.c

如果int * foo_ptr在pthread_join()之后,它会导致我崩溃:

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

void *somefunction(void *vargp);


int main(int argc, char **argv){
    if (argc < 2){
        fprintf(stderr, "Invalid usage, bleh\n");
        return 1;
    }
    int argu = atoi(argv[1]);
    pthread_t tid;
    int rc = pthread_create(&tid, NULL, somefunction, &argu);
    assert (rc == 0);
    void **retval;
    pthread_join(tid, retval);
    int foo = 10;
    int *foo_ptr = &foo; // <-------- this line causes a crash 
    printf("retval is %d\n", **(int **)retval);

    printf("*foo_ptr is %d\n", *foo_ptr );


    pthread_exit(NULL);
}


void *somefunction(void *vargp){
    int *someint = (int *) vargp ;
    *someint = *someint * 3;
    printf("In somefunction, someint value is %d\n", *someint);
    pthread_exit(someint);
}

谢谢!

2 个答案:

答案 0 :(得分:2)

您应该更像这样使用pthread_join()

void *rv;
int err;

if ((err = pthread_join(tid, &rv)) != 0)
    …report join failure using err…
else
    …rv points to what the thread returned…

这会将void **传递给pthread_join(),但它与您所做的不同 - 它会将指针传递给void *变量,而不是未初始化的值。

请注意,返回的指针必须(应该)是指向线程函数退出后存活的指针 - 全局变量,动态分配的内存,或者可能指向 通过在启动时传递给线程函数的参数或类似的东西使函数可用的内存。从线程函数的堆栈返回指向int变量的指针是完全且完全不可靠的。如果仔细研究,你的代码会使用作为参数传递给函数的指针,这样就可以安全了。

答案 1 :(得分:1)

关于事业的红鲱鱼。 OS X上的编译在'retval'处爆炸。

你有一个“无效**”,但你要做的是传递将用退出值填入的值。你需要为它创建一些存储空间,但你所做的只是传入一个未初始化的指针。

int main(int argc, char **argv){
    int argu = 21;
    pthread_t tid;
    int rc = pthread_create(&tid, NULL, somefunction, &argu);
    assert (rc == 0);
    void *retval = NULL;
    pthread_join(tid, &retval);
    int foo = 10;
    int *foo_ptr = &foo;
    printf("retval is %d\n", *(int *)retval);

    printf("*foo_ptr is %d\n", *foo_ptr );

    pthread_exit(NULL);
}
编辑:您的代码有点迟钝但是当线程关闭并且其堆栈被丢弃时,您实际上没有'someint'在'somefunction'中消失的问题,因为'someint'实际上只是传递的值in,传入的值是指向指向main堆栈中整数的指针。