2016-04-24 11 views
0

こんにちは私は条件付き変数を使用して分離されたスレッドを同期しようとしていますが、時々メモリリークを引き起こすバグを発見しました。私はコードが自明だと思う。私は何かアドバイスをいただければ幸いです。POSIXスレッド - 条件付き変数MEMORY LEAKを使用してDETACHEDスレッドを同期する

#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()にした唯一のジョブを持つ1つのシングルトンバックグラウンドスレッドを開始しました。次に、フレームワークによって開始された各スレッドは、各スレッドが終了する直前に、シングルトンバックグラウンドスレッドの独自のスレッドIDをキューに入れます。

ネットエフェクトは、分離スレッドと同等でした。私は各スレッドを開始することができ、それに参加する心配はありません。それはバックグラウンドスレッドの仕事になるだろう。フレームワークは、終了する前にバックグラウンドスレッドに自身を終了させ、結合するように通知します。したがって、すべてがうまくいく場合、スレッドのサポートに説明できるメモリリークは報告されません。

+0

情報ありがとうございますが、上のコードを編集するだけで漏れを防ぐための「クリーンな」方法はありますか? – guderkar

+0

スレッドによって使用されるすべてのリソースが解放されることを知る唯一の方法は、それに参加することです。スレッド内で最後に実行されたアクションとスレッドが実際に終了してそのすべてのリソースを解放したときの間に、常に競合状態が存在します。 –

+0

ありがとうございます。 – guderkar

関連する問題