linux c-pthreads: проблема с локальными переменными - PullRequest
1 голос
/ 23 мая 2011

пытается вычислить число Фибоначчи с потоками. Всегда возвращаются 1. Любые предложения?

мой код:

#include <stdio.h>  
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
/* compile with -lpthread */
void*  fibo (void* param) {
    int    a,b,n;
    pthread_t thread_a, thread_b;
    int ret;

    n = (int) param;
    if (n>1)
    {    pthread_create(&thread_a,NULL,fibo,(void*)(n-1));    
        pthread_create(&thread_b,NULL,fibo,(void*)(n-2));
        pthread_join(thread_a,(void**)&a);
        pthread_join(thread_b,(void**)&b);
        ret=a+b;
    }
    else    ret=1;
    return (ret);    
    /*pthread_exit((void**)ret);*/
}

int main(int argc,char* argv[]) {
    pthread_t thread_id;
    int n,ret;
    n=atoi(argv[1]);
    pthread_create(&thread_id,NULL,fibo,(void*)n);
    pthread_join(thread_id,(void**)&ret);
    printf("s(%d)=%d\n",n,ret);
    return 0;
}

Ответы [ 3 ]

6 голосов
/ 23 мая 2011

Я предполагаю, что вы, вероятно, используете 64-битную систему.

Ваша проблема в pthread_join:

int n,ret;
pthread_join(thread_id,(void**)&ret);

В 64-битных системах ints 32 бит, но void* 64 бит.Итак, вы пытаетесь хранить 64 бита в 32-битной переменной.В результате вы перезаписываете другие места в стеке и просто делаете кучу вещей.Обязательно восстановите значение в истинное void *, и все должно работать лучше.Еще лучше использовать указатель void* в качестве истинного указателя;Например, вы можете передать указатель на int в качестве аргумента функции потока и использовать его в качестве аргумента, а затем записать результат в то же место.

Кстати, GCC предупреждает об этом, даже безлюбые предупреждающие переключатели:

test.c:30: warning: cast to pointer from integer of different size

Пожалуйста, не игнорируйте эти предупреждения.

1 голос
/ 23 мая 2011

Ошибка:

n = (int) param;

, тогда как param является void *. Итак, вы конвертируете указатель в int , что, вероятно, дает отрицательное число, и управление переходит к else branch:)

РЕДАКТИРОВАТЬ: но здесь все еще может быть предупреждение: ошибка: приведение от 'void *' к 'int' теряет точность

0 голосов
/ 23 мая 2011

Потоки не используют одни и те же локальные переменные, поскольку локальные переменные находятся в стеке, и каждый поток имеет свой собственный стек. Потоки do совместно используют глобальные переменные, если они не созданы явно для локальных потоков.

Вы можете создать локальное хранилище потоков в pthreads, используя pthread_key_create и связанные с ними функции.

(как указывает лоза, это не относится к делу, поскольку ваша ошибка не связана с потоками)

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