2017-07-13 44 views
1

我寫了這個小程序來理解pthread_create和pthread_join,但我不明白爲什麼變量data的值在thread_join之後被修改。它在調用pthread函數後打印爲0。作爲參考傳遞的變量的值在線程中發生了變化

#include <pthread.h> 
#include <stdio.h> 
void* compute_prime (void* arg) 
{ 
     int n = *((int*) arg); 
     printf("Argument passed is %d\n",n); 
     return (void *)n; 
} 
int main() 
{ 
     pthread_t thread; 
     int data = 5000; 
     int value=0; 

     pthread_create (&thread, NULL, &compute_prime, &data); 
     pthread_join (thread, (void*) &value); 
     printf("The number is %d and return value is %d.\n", data, value); 
     return 0; 
} 

,輸出是

Argument passed is 5000 
The number is 0 and return value is 5000. 
+0

''中pthread_join' value'被設置爲線程的返回值。這裏,這意味着線程函數返回的'n'的值爲 –

+0

@CraigEstey問題是數據變化的原因。我沒有看到這段代碼改變它,即使在'return(void *)n;'中投了錯。可能有代碼缺失。 –

+0

'return(void *)n;'返回一個指向局部變量的指針,不是嗎? –

回答

5

這是因爲pthread_join有原型void **。它期望指針void *類型的對象;它會修改這個對象。現在恰好你運行的是64位拱,其中datavalue都是32位,並按順序排列在內存中。修改void *對象,該對象從int對象value對象int對象data的地址開始,因爲它們都是32位 - 因此您將看到data被覆蓋。但是,這是未定義的行爲,所以可能發生任何事情。


不要使用強制轉換,因爲它們只會用於隱藏問題。鑄造到void *是特別危險的,因爲void *可以隱式轉換爲任何其他類型,甚至到void **,即使通常它也會不正確。如果刪除演員陣容,則很可能會收到警告或錯誤信息,例如

thrtest.c: In function ‘main’: 
thrtest.c:16:31: error: passing argument 2 of ‘pthread_join’ from 
       incompatible pointer type [-Werror=incompatible-pointer-types] 
     pthread_join (thread, &value); 

如果編譯時啓用了警告。


然而,如果你真的想這樣做,你必須做這樣的:

void *value; 
pthread_join(thread, &value); 
intptr_t value_as_int = (intptr_t)value; 

雖然它不是真正的便攜式或者,作爲轉換是實現定義的。

最便攜的方式來返回一個整數是將指針返回給malloc ated對象:

int *return_value = malloc(sizeof (int)); 
*return_value = 42; 
return return_value; 

... 

void *value; 
pthread_join(thread, &value); 
int actual = *(int *)value; 
free(value); 
+0

正是我現在發現的;) –

+0

如果你只是想從一個線程函數返回一個數字,把它轉換爲'intptr_t',但是想到...... –

+0

是的,那麼可以通過將數據定義爲'unsigned long long int'來確認這一點? –

相關問題