2010-02-12 33 views
40

我是C新手,並且想用線程來玩一下。我想從使用pthread_exit()如何從C中的線程返回一個值

我的代碼線程返回一些值如下:

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

void *myThread() 
{ 
    int ret = 42; 
    pthread_exit(&ret); 
} 

int main() 
{ 
    pthread_t tid; 
    void *status; 

    pthread_create(&tid, NULL, myThread, NULL); 
    pthread_join(tid, &status); 

    printf("%d\n",*(int*)status); 

    return 0; 
} 

我希望節目輸出「42 \ n」,但它輸出的隨機數。我怎樣才能打印返回的值?

編輯: 根據第一個答案,問題是我正在返回指向本地變量的指針。返回/存儲多個線程變量的最佳做法是什麼?全局散列表?

在此先感謝

+1

響應於編輯:我會傾向於如果我需要提供多個線程使用的陣列,每個具有一個地方寫它們的結果。如果您事先不知道您要創建多少個線程的上限,那麼我通常會認爲這是一個問題。但是一般來說,任何結構都可以,只要啓動線程的人可以確保線程存儲其結果的位置;線程被告知在哪裏存儲它;誰加入線程可以恢復結果,如果有必要釋放它。如果線程以相同的值退出,它將作爲參數傳遞,這可以提供幫助。 – 2010-02-12 12:08:42

回答

34

您正在返回局部變量的地址,該變量在線程函數退出時不再存在。無論如何,爲什麼要調用pthread_exit?爲什麼不簡單地從線程函數返回一個值?

void *myThread() 
{ 
    return (void *) 42; 
} 

,然後在主:

printf("%d\n",(int)status); 

如果需要返回一個複雜的值這樣的結構,它可能比較容易通過的malloc動態分配它(),並返回一個指針。當然,啓動線程的代碼將負責釋放內存。

+1

如果你的意思是「爲什麼不是」,那麼原因不是將42投射到指針類型是未定義的行爲。當然,如果它做了什麼壞事,它就是其中的一個「這是一個C實現,吉姆,但不是我們所知道的」時刻。 – 2010-02-12 11:49:07

+0

@Steve有時候我會冒險一點UB - 這是其中之一 - 替代品如此混亂。 – 2010-02-12 11:50:31

+0

我也是,但我不會把「隨身攜帶的任何地方」貼紙放在盒子上。 – 2010-02-12 11:51:13

3

我認爲你必須在堆上存儲數字。 int ret變量在堆棧中並在函數myThread執行結束時被破壞。

void *myThread() 
{ 
     int *ret = malloc(sizeof(int)); 
     if (ret == NULL) { 
      // ... 
     } 
     *ret = 42; 
     pthread_exit(ret); 
} 

不要忘記free它時,你不需要它:)

另一種解決方案是返回數字作爲指針的值,如尼爾·巴特沃思建議。

+0

pthread_exit只接受指針作爲參數是很愚蠢的:( – 2010-02-12 11:42:15

+3

它不是「笨」,它是C類型系統的限制。爲了通過pthreads系統返回一個任意類型的參數,你需要一個Python風格對象系統,其中變量沒有類型,只有值可以,或者你需要很多C++模板技術,完全一樣,你只能從線程入口點返回'void *',你不能return(eg)double。 – 2010-02-12 12:04:26

+1

另外不要忘記,檢查'malloc'工作:-) – 2014-10-23 20:16:36

25

您已經返回了指向局部變量的指針。即使線程沒有涉及,這也很糟糕。

執行此操作的常用方法是,當啓動的線程與連接的線程相同時,將作爲pthread_create的第四個參數將指針傳遞給由調用方管理的位置中的int。然後這成爲線程入口點的(唯一)參數。您可以(如果你喜歡)使用線程退出值來表示成功:

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

int something_worked(void) { 
    /* thread operation might fail, so here's a silly example */ 
    void *p = malloc(10); 
    free(p); 
    return p ? 1 : 0; 
} 

void *myThread(void *result) 
{ 
    if (something_worked()) { 
     *((int*)result) = 42; 
     pthread_exit(result); 
    } else { 
     pthread_exit(0); 
    } 
} 

int main() 
{ 
    pthread_t tid; 
    void *status = 0; 
    int result; 

    pthread_create(&tid, NULL, myThread, &result); 
    pthread_join(tid, &status); 

    if (status != 0) { 
     printf("%d\n",result); 
    } else { 
     printf("thread failed\n"); 
    } 

    return 0; 
} 

如果你絕對要使用的結構線出口值,那麼你就必須動態地分配它(並確保誰加入線程釋放它)。雖然這並不理想。

+2

我剛剛發現了這一點,但根據http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_exit .html你不需要在線程的函數調用中使用pthread_exit。 「線程終止的正常機制是從啓動它的pthread_create()調用中指定的例程返回。pthread_exit()函數提供了線程終止的功能,無需從啓動例程返回該線程,從而提供類似於exit()的功能。「 pthread_exit應該用於提前終止。 – 2014-08-27 04:05:21

+1

'printf(「thread failed \ n」);' - 我會用'fprintf'將錯誤信息打印到'stderr'。 – 2015-12-28 05:56:35

2

您正在返回參考ret這是一個變量在堆棧上。

1

問題:返回/存儲多線程變量的最佳做法是什麼?全局散列表?

這完全取決於你想要返回什麼以及如何使用它?如果你只想返回線程的狀態(比如線程是否完成了它想做的事情),那麼就使用pthread_exit或者使用return語句從線程函數返回值。

但是,如果你想要一些更多的信息將被用於進一步處理,那麼你可以使用全局數據結構。但是,在這種情況下,您需要通過使用適當的同步原語來處理併發問題。或者您可以分配一些動態內存(最好是用於存儲數據的結構)並通過pthread_exit發送,並且一旦線程加入,就會在另一個全局結構中更新它。通過這種方式,只有一個主線程會更新全局結構並解決併發問題。但是,您需要確保釋放由不同線程分配的所有內存。

0

如果您對返回地址感到不舒服,並且只有一個變量,例如。一個返回的整數值,你甚至可以在傳遞它之前將它轉換爲(void *),然後當你在main中收集它時,再次將它轉換爲(int)。你有價值而不會拋出醜陋的警告。

11

這是一個正確的解決方案。在這種情況下,tdata被分配在主線程中,並且線程有一個空間來放置其結果。

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

typedef struct thread_data { 
    int a; 
    int b; 
    int result; 

} thread_data; 

void *myThread(void *arg) 
{ 
    thread_data *tdata=(thread_data *)arg; 

    int a=tdata->a; 
    int b=tdata->b; 
    int result=a+b; 

    tdata->result=result; 
    pthread_exit(NULL); 
} 

int main() 
{ 
    pthread_t tid; 
    thread_data tdata; 

    tdata.a=10; 
    tdata.b=32; 

    pthread_create(&tid, NULL, myThread, (void *)&tdata); 
    pthread_join(tid, NULL); 

    printf("%d + %d = %d\n", tdata.a, tdata.b, tdata.result); 

    return 0; 
} 
+0

這是最乾淨的例子 - 我很驚訝它沒有更高的優先級。特別是它表明,在調用級別管理存儲是正確的事情 - 同時指針可以用於傳遞更復雜的結構 - 無論是進出。 – Floris 2017-04-11 13:03:05

2
#include<stdio.h> 
#include<pthread.h> 
void* myprint(void *x) 
{ 
int k = *((int *)x); 
printf("\n Thread created.. value of k [%d]\n",k); 
//k =11; 
pthread_exit((void *)k); 

} 
int main() 
{ 
pthread_t th1; 
int x =5; 
int *y; 
pthread_create(&th1,NULL,myprint,(void*)&x); 
pthread_join(th1,(void*)&y); 
printf("\n Exit value is [%d]\n",y); 
} 
+0

從線程函數返回局部變量的值。而不使用全局變量。 – Abhishek 2014-11-18 08:14:24