указатель на int после pthread_join () вызывает сбой - PullRequest
0 голосов
/ 21 мая 2018

Работая с pthreads, я столкнулся с запутанной проблемой.

Если я определю int-указатель после pthread_join, это может привести к сбою программы.В любом месте до 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);
}

fails.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 голосов
/ 21 мая 2018

Красная сельдь по делу.Компиляция в OS X взорвалась при 'retval'.

У вас там есть "void **", но вы хотите передать значение, которое будет заполнено значением выхода,Для этого вам нужно создать какое-то хранилище, но все, что вы делаете, это передаете неинициализированный указатель.

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 - это на самом деле просто переданное значение, а переданное значение было указателем на целое число в стекев main.

0 голосов
/ 21 мая 2018

Ожидается, что вы будете использовать 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 из стека функции потока совершенно и совершенно ненадежно.При достаточно тщательном изучении ваш код использует указатель, который был передан в качестве аргумента функции, так что многое из этого безопасно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...