0

Я сделал следующий код.Доступ к возвращаемому значению с использованием pthread_exit()

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

struct foo 
{ 
    int a; 
    int b; 
}; 

void* thread_func1(void *arg) 
{ 
    struct foo *temp = (struct foo*)malloc(sizeof(struct foo)); 

    temp->a = 10; 
    temp->b = 20; 

    pthread_exit(temp); 
} 

void* thread_func2(void *arg) 
{ 
    pthread_exit((void*)100); 
} 

int main() 
{ 
    pthread_t tid1, tid2; 
    int err; 
    struct foo *f; 
    void *ret; 

    err = pthread_create(&tid1, NULL, thread_func1, NULL); 
    err = err | pthread_create(&tid2, NULL, thread_func2, NULL); 

    if(err != 0) 
    { 
     perror("pthread_create()"); 
     exit(-1); 
    } 

    err = pthread_join(tid1, (void**)&f); 
    if(err != 0) 
    { 
     perror("pthread_join1"); 
     exit(-1); 
    } 

    printf("a = %d, b = %d\n", f->a, f->b); //Line1 

    err = pthread_join(tid2, &ret); 
    if(err != 0) 
    { 
     perror("pthread_join2"); 
     exit(-1); 
    } 

    printf("ret = %d\n", *(int*)ret); //Line2 

    return 0; 

} 

Я получаю ошибку сегментации на линии 2. Что случилось с Line2

Если я изменить line2 к

Е ("РЭТ =% d \ п", (INT) в отставке);

отсутствует ошибка сегментации, и он печатает правильное значение (то есть 100). Я не понимаю, почему работает модификация. Я считаю, что у меня неправильная концепция использования двойных указателей. Я хотел бы исправить это.

В чем причина ошибки Сегментации и почему эта модификация работает?

+0

Sidenote: Используйте 'malloc' нравится это:' структура Foo * Темп = таНос (SizeOf (* темп)); 'Вы оцените это, когда вы понимаете преимущества. – Shahbaz

+0

Не связано с вашей проблемой, но вы не освобождаете значения, возвращаемые первой функцией потока. –

+0

@JoachimPileborg: Точка отмечена !. 'free' должно быть выполнено после доступа к значениям, используя f-> a и f-> b вправо? –

ответ

2

Вы возвращаетесь один номер из потока. В первом потоке это число равно struct foo *. Поэтому, если вы говорите,

pthread_join(tid1, &ret); 

затем ret будет содержать этот указатель (который не двойной указатель).

Аналогичным образом во втором случае вы возвращаете 100, хотя вы смотрите на него, как будто это void *. Тем не менее, значение по-прежнему 100!

Поэтому, когда вы пишете

pthread_join(tid2, &ret); 

ret будет содержать 100, который не является указателем, а простое число. Вот почему вы должны также бросить его на int.

Причина, по которой вы получили ошибку сегментации, состоит в том, что вы смотрите на 100 как int *, а затем попытаетесь разыменовать ее.

3

Это потому, что вы возвращаете фактическое целое число, а не указатель, но вы обращаетесь к нему как к указателю.

+1

+1 Великие мысли думают одинаково, вы избили меня на 14 секунд :) – Brady

+1

@Brady Да, может быть ... :) Но ваш ответ содержит альтернативное решение. –

1

его потому, что вы пытаетесь dereferencce указатель, адрес которого равен 100.

Вместо того, чтобы смотреть на возвращаемое значение, то почему бы вам не передать указатель на то, что вы хотите назначить в thread_funcs? То есть, использовать "недействительным * аргумент" аргументы thread_func1() и thread_func2()

Как это:

void* thread_func1(void *arg) 
{ 
    struct foo **fooPtrPtr = (struct foo**) arg; 
    *fooPtrPtr = (struct foo*)malloc(sizeof(struct foo)); 

    ... 
} 

void* thread_func2(void *arg) 
{ 
    int *intPtr = arg; 
    *intPtr = 100; 
    ... 
} 

int main() 
{ 
    pthread_t tid1, tid2; 
    int err; 
    struct foo *f; 
    int ret; 

    err = pthread_create(&tid1, NULL, thread_func1, &f); 
    err = err | pthread_create(&tid2, NULL, thread_func2, &ret); 
    ... 
    printf("a = %d, b = %d\n", f->a, f->b); //Line1 
    ... 
    printf("ret = %d\n", ret); //Line2 
    ... 
} 
1

pthread_exit((void*)100); вызывает целое число 100, чтобы стать статусом выхода вашей нити. Он просто злоупотребляет типом, так что void* является его типом. Если вы хотите, чтобы получить это значение, вы должны будете использовать тот же тип злоупотребления произнесения в основном потоке, а также:

int ret; 
err = pthread_join(tid2, (void**) &ret); 
// here you can work with ret as with any other integer 

Я также предлагаю вам использовать return вместо pthread_exit.Также обратите внимание, что память, динамически распределенная с использованием malloc, должна быть освобождена, вызывая free. И тип cast возвращаемого значения malloc здесь избыточен, его можно опустить.

Этот вопрос также может помочь вам: Close a thread when done with it