2013-11-20 77 views
2

這裏是我的程序只是爲了找到pthread_exit和線程返回之間的區別。pthread_exit vs posix線程返回

struct foo{ 
    int a,b,c,d; 
    ~foo(){cout<<"foo destructor called"<<endl;} 
}; 
//struct foo foo={1,2,3,4}; 
void printfoo(const char *s, const struct foo *fp) 
{ 
    cout<<s; 
    cout<<"struct at 0x"<<(unsigned)fp<<endl; 
    cout<<"foo.a="<<fp->a<<endl; 
    cout<<"foo.b="<<fp->b<<endl; 
    cout<<"foo.c="<<fp->c<<endl; 
    cout<<"foo.d="<<fp->d<<endl; 
} 
void *thr_fn1(void *arg) 
{ 
    struct foo foo={1,2,3,4}; 
    printfoo("thread1:\n",&foo); 
    pthread_exit((void *)&foo); 
    //return((void *)&foo); 
} 
int main(int argc, char *argv[]) 
{ 
    int err; 
    pthread_t tid1,tid2; 
    struct foo *fp; 
    err=pthread_create(&tid1,NULL,thr_fn1,NULL); 
    if(err!=0) 
      cout<<"can't create thread 1"<<endl; 
    err=pthread_join(tid1,(void **)&fp); 
    if(err!=0) 
      cout<<"can't join with thread 1"<<endl; 
    exit(0); 
} 

在「* thr_fn1」線程函數中,我創建了一個對象foo。

據現場pthread_exit vs. return 當我退出線程函數 「thr_fun1()」 使用 「返回((無效*)&富);」它應該調用對象foo的析構函數,但是當我調用「pthread_exit((void *)& foo)時,它不應該調用析構函數;」從函數「thr_fun1()」返回到main。

但是在兩種情況下都使用「return((void *)& foo);」或「pthread_exit((void *)& foo);」函數「thr_fun1()」中的本地對象「foo」正在被調用。

這不是我猜測的行爲。析構函數只能在「return((void *)& foo)中調用;」只有情況。

請確認我是否錯了?

回答

3

是的,沒錯。 pthread_exit()立即退出當前線程,而不調用堆棧中較高位置的對象的任何析構函數。如果你用C++編碼,你應該確保你的線程過程總是return,或者只從最底層的堆棧幀之一調用pthread_exit(),沒有任何對象在該幀或更高幀中仍然存在;否則,您將泄漏資源或導致其他不良問題。

+0

我改變了問題。請在任何編輯器中編譯並回復。 –

+0

「其他不好的問題」包括這樣的混亂,例如沒有釋放由以這種方式被終止的線程獲取/擁有的同步對象(互斥體等)的所有權。 – Bukes

3

您的代碼存在嚴重問題。具體而言,您使用的是局部變量作爲了pthread_exit()退出值:

void *thr_fn1(void *arg) 
{ 
    struct foo foo={1,2,3,4}; 
    printfoo("thread1:\n",&foo); 
    pthread_exit((void *)&foo); 
    //return((void *)&foo); 
} 

Pthreads spec,「一個線程終止後,獲得了線程的本地(自動)變量的結果是不確定的。

因此,從您的線程函數作爲線程退出值返回堆棧分配的變量的地址(在你的情況下,pthread_exit((void *)&foo))將導致問題,爲檢索並試圖取消引用該地址的任何代碼。

+0

根據Pthreads規範,它寫道:「如果從取消清除處理程序或由於對pthread_exit()的隱式或顯式調用而調用的析構函數調用pthread_exit()的行爲未定義。而在我的情況下,我不是從析構函數或清理處理函數調用pthread_exit。我從線程本身調用它。請提供更多正確的細節 –

+1

@Santosh Sahu規範特別指出:「線程終止後,線程的本地(自動)變量訪問結果未定義,因此不應使用對現有線程局部變量的引用爲pthread_exit()value_ptr參數值。「,這正是你的示例正在做的。現在,關於這個downvote .... – Bukes

+0

這裏是你upvote ... –

2

pthread_exit()正在拋出一個異常,導致堆棧展開併爲當地人調用析構函數。有關更多詳細信息,請參閱https://stackoverflow.com/a/11452942/12711

拋出的異常類型爲abi::__forced_unwind(來自cxxabi.h);互聯網搜索可以給你更多的細節。


注:其他答案/評論都提到,返回一個本地的地址不反正工作,但是這是除了問題的要點。如果返回一些其他有效地址(或空指針)而不是&foo,則會破壞foo