2016-05-31 84 views
0

我知道通過調用pthread_joinpthread_detach會釋放線程在完成後使用的資源,但我的情況並不那麼容易。pthread完成後泄漏內存

首先,我希望能夠從父線程終止子線程,所以我寫了這樣的內容:(動態分配的buf在那裏顯示我似乎無法找到一種方法來使用pthread_detach因爲我不知道如何等待子線程完成(所以我可以免費製造)如果我分開它)

bool running = true; 
void *foo(void *buf) 
{ 
    while (running) 
    { 
     // Do something with buf 
    } 

    return NULL; 
} 

int main(int argc, char **argv) 
{ 
    char *buf = new char[1024]; 

    pthread_t tid; 
    pthread_create(&tid, NULL, foo, buf); 

    string cmd; 
    while (true) 
    { 
     cin >> cmd; 

     if (!cmd.compare("stop")) 
     { 
      running = false; 
      pthread_join(tid, NULL); 
      delete[] buf; 
     } 
     else 
     { 
      // Do something 
     } 
    } 

    return 0; 
} 

這似乎工作。但是,在父線程想要終止它之前,子線程有時會結束。在這種情況下,父線程被阻塞,所以

  1. 如何通知父線程的子線程終止因此父線程可以調用pthread_join

  2. 是否有使用pthread_detach,仍然能夠等待子線程來完成,所以我可以自由BUF之後(但它似乎我可以在這個演示子線程釋放BUF的方式,這對我是不可能的真正的應用)?

+0

不完全確定你在這裏嘗試的是什麼。 'pthread_join'阻塞,直到線程完成,如果尚未完成。如果線程需要很長時間才能退出,這可能是'main'中的一個問題,但是您不必擔心漏掉了退出。 – user4581301

+0

@ user4581301問題是如果我使用'pthread_join',那麼當子線程完成時它必須告訴父線程調用'pthread_join'。如果我使用'pthread_detach',我將無法等待子線程完成。 – MegaStupidMonkeys

回答

2
  1. 如何通知父線程的子線程終止因此父線程可以調用pthread_join函數?

有各種各樣的選擇。這裏有三個合理有希望的:

  • 你可以讓子線程設置一個全局標誌變量。

  • 您可以讓子線程信號爲pthread_kill()的父線程。

  • 您可以設置一個管道,當子進程完成時,它會寫入一個管道,並讓父服務器執行非阻塞讀取操作,以測試子進程是否完成。

  • 是否有使用pthread_detach,仍然能夠等待子線程來完成,所以我可以自由BUF之後(儘管它 看來我獨有的方式來免費在這個演示中的子線程buf,這對我的真實應用來說不可能是 )?
  • 不可以。一旦線程被分離,它就不能被連接。

    你可以考慮讓線程管理自己的資源。或者,如果主線程必須分配資源,那麼至少考慮將管理它們的責任交給子線程。

    0

    如何通知父線程子線程已終止,以便父線程可以調用pthread_join?

    你有沒有考慮過使用std :: thread?

    我想下面的代碼表明你不需要使用std :: thread做任何事情。 sleep_for()足夠人類觀看。

    void pause_thread(int n, std::string lbl) 
    { 
        std::this_thread::sleep_for (std::chrono::seconds(n)); 
        std::cout << lbl << " pause of " << n << " seconds ended" << std::endl; 
    } 
    
    int t403(void) 
    { 
        std::cout << "Spawning 3 threads...\n" << std::flush; 
        std::thread t1 (pause_thread, 6, "t1"); 
        std::thread t2 (pause_thread, 3, "t2"); 
        std::thread t3 (pause_thread, 1, "t3"); 
        std::cout << "Done spawning threads, " 
         "Note that they finish out-of-order. \n" 
         "Now 'main' thread waits for spawned threads to join:\n" << std::flush; 
    
        t1.join(); std::cout << "join t1 " << std::flush; 
        t2.join(); std::cout << "join t2 " << std::flush; 
        t3.join(); std::cout << "join t3 " << std::flush; 
        std::cout << "completed join \n" 
         "note: \n - join sequence is in-order, but finish sequence is out-of-order\n" 
         " - inference: the threads waited for main to join! "<< std::endl; 
    
        return(0); 
    } 
    

    更新:2016年6月1日

    我已複製使用POSIX線程,並加入上述方案。看來主線程不需要通知一個衍生線程已經終止。

    此外,從 「人在pthread_join」:

    的在pthread_join()函數等待由 '線' (參數1)指定爲終止線程。如果該線程已經終止,則 然後pthread_join()立即返回。 線程指定的線程必須可以連接。

    也許我錯過了一些關於你的問題。

    也許發佈連接的線程在這段時間內不應該試圖做任何事情。

    考慮將「其他」移動到它自己的合作線程中?

    0

    我要走向不同的方向。這個問題不應該是「我如何表示線程結束,所以我可以釋放buf?」它應該是「我應該如何爲buf分配所有權,最好是以線程末尾無關緊要的方式?」

    foomain應該釋放buf。那麼哪個?

    案例1:buf被分配但未被使用的由main

    此情況下,包括buf分配和main初始化只要main不消耗buf線程完成處理後。這種情況很容易。線程假定buf的所有權,並在線程完成時將其刪除。

    void *foo(void *buf) 
    { 
        while (running) 
        { 
         // Do something with buf 
        } 
        delete buf; 
        return NULL; 
    } 
    

    案例2:bufmain分配,操作上由foo,然後通過main消耗。

    顯然buf必須是活的main來使用它,所以main應保留所有權和使用後刪除buf。但當?這意味着它必須等待foo完成處理buf,這意味着加入或完成消息。現在我們看看約翰布林傑的答案。

    案例3:buf被分配在foo中,由foo運行,並被foo刪除。

    這有沒有混亂的優勢是什麼,所以有史以來,如果main從不接觸 bufmain應該完全放手,包括分配。在一個完美的世界裏,這看起來像:

    void *foo(void *) 
    { 
        char buf[1024]; 
        while (running) 
        { 
         // Do something with buf 
        } 
        return NULL; 
    } 
    

    緩衝區的大小,如果知道main,但不foo,可以提供給線程。例如,

    pthread_create(&tid, NULL, foo, &bufsize); 
    

    void *foo(void * size) 
    { 
        char * buf = new char[*((int*)size)]; 
        while (running) 
        { 
         // Do something with buf 
        } 
        delete buf; 
        return NULL; 
    } 
    

    ,但你應該更喜歡

    void *foo(void * size) 
    { 
        std::unique_ptr<char[]> buf(new char[*((int*)size)]); 
        while (running) 
        { 
         // Do something with buf 
        } 
        return NULL; 
    } 
    

    避免原始指針。

    只需確保bufsizefoo開始之前不會更改。