2016-04-24 46 views
0

你好我正嘗試使用條件變量同步分離的線程,但是我發現了一個有時會導致內存泄漏(取決於調度程序心情)的錯誤。我認爲這個代碼是自我解釋的。我將不勝感激任何建議。POSIX線程 - 使用條件變量同步DETACHED線程MEMORY LEAK

#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#include <unistd.h> 
#include <pthread.h> 

using namespace std; 

struct TThrArg 
{ 
    pthread_t m_ID; 
    bool  m_IsRunning; 
}; 

TThrArg   g_Threads[64]; 
int    g_Counter; 
pthread_mutex_t g_Mtx; 
pthread_cond_t g_Cond; 

void * thrFunc (void * arg) 
{ 
    TThrArg * data = (TThrArg *) arg; 

    // do some stuff 
    // ----------------------------------- 
    // for (int i = 0; i < 5000; ++i) 
    // for (int j = 0; j < 5000; ++j) 
    //  int x = 0; 
    // printf("Thread: %lu running...\n", data->m_ID); 
    // ----------------------------------- 

    pthread_mutex_lock(&g_Mtx); 
    memset(data, 0, sizeof(TThrArg)); 
    --g_Counter; 
    pthread_cond_signal(&g_Cond); 
    pthread_mutex_unlock(&g_Mtx); 
    sleep(1); // --> this spot causes that main may end before return NULL so resources will not be freed 
    return NULL; 
} 

void createThread (void) 
{ 
    pthread_mutex_lock(&g_Mtx); 
    for (int i = 0; i < 64; ++i) 
    { 
     if (g_Threads[i].m_IsRunning == 0) 
     { 
      g_Threads[i].m_IsRunning = 1; 
      ++g_Counter; 

      pthread_attr_t attr; 
      pthread_attr_init(&attr); 
      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 
      pthread_create(&g_Threads[i].m_ID, &attr, thrFunc, &g_Threads[i]); 
      pthread_attr_destroy(&attr); 

      break; 
     } 
    } 
    pthread_mutex_unlock(&g_Mtx); 
} 

int main (int argc, char * argv[]) 
{ 
    pthread_mutex_init(&g_Mtx, NULL); 
    pthread_cond_init(&g_Cond, NULL); 
    g_Counter = 0; 

    for (int i = 0; i < 64; ++i) 
     createThread(); 

    pthread_mutex_lock(&g_Mtx); 
    while (g_Counter != 0) 
    { 
     pthread_cond_wait(&g_Cond, &g_Mtx); 
    } 
    pthread_mutex_unlock(&g_Mtx); 

    pthread_mutex_destroy(&g_Mtx); 
    pthread_cond_destroy(&g_Cond); 

    return 0; 
} 

回答

0

您看到的泄漏是因爲終止線程遞減受互斥鎖保護的線程計數器,並在線程實際終止之前暫停一秒。

主執行線程會立即看到線程計數器達到0,並在實際分離的線程退出之前終止。每個正在運行的線程,即使是一個分離的線程,都會消耗和分配一些內部內存,直到線程實際終止時纔會釋放內存。這是您看到的泄漏,從主執行線程停止前沒有終止的執行線程。

這不是你需要擔心的泄漏。這很煩人,並且使調試困難,真實。

過去,我在前一段框架類庫中採用了一種方法。我根本沒有使用分離的線程,但所有的線程都是可連接的線程。該框架啓動了一個單獨的後臺線程,其唯一的工作是終止線程join()。然後,在每個線程終止之前,由框架啓動的每個線程都會爲單例後臺線程排隊自己的線程ID。

淨效果相當於分離的線程。我可以開始每個線程,而不用擔心加入它。這將成爲後臺線程的工作。該框架將指示後臺線程自行終止,並在退出之前加入它。所以,如果一切順利的話,不會有任何報告的內存泄漏可以歸因於線程支持。

+0

感謝您的信息,但是有沒有「乾淨」的方式來防止泄漏,只需編輯上面的代碼? – guderkar

+0

沒有。知道一個線程使用的所有資源的唯一方法就是加入它。在線程中執行的最後一個動作與線程實際終止並釋放其所有資源之間始終存在爭用條件。 –

+0

非常感謝您的先生。 – guderkar