简体   繁体   English

POSIX线程-使用条件变量MEMORY LEAK同步已分离的线程

[英]POSIX Threads - synchronize DETACHED threads using conditional variable MEMORY LEAK

Hello I'm trying to synchronize detached threads using conditional variable, but I found a bug that sometimes causes memory leak (depends on scheduler mood). 您好,我正在尝试使用条件变量来同步分离的线程,但是我发现了一个有时会导致内存泄漏的错误(取决于调度程序的心情)。 I think the code is self explanatory. 我认为代码是不言自明的。 I would appreciate any advice. 我将不胜感激任何建议。

#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;
}

The leak you see is because the terminating thread decrements the mutex-protected thread counter, and pauses for a second before the thread actually terminates. 您看到的泄漏是因为终止线程减少了互斥锁保护的线程计数器,并在该线程实际终止之前暂停了一秒钟。

The main execution thread will immediately see that the thread counter reached 0, and terminate before the actual detached threads have exited. 主执行线程将立即看到线程计数器达到0,并在实际的分离线程退出之前终止。 Each running thread, even a detached thread, consumes and allocates a little bit of internal memory, which does not get released until the thread actually terminates. 每个正在运行的线程,甚至是分离的线程,都会消耗并分配一小部分内部内存,直到该线程实际终止后,内部内存才会释放。 This is the leak you see, from execution threads that did not terminate before the main execution thread stopped. 这是从主执行线程停止之前未终止的执行线程看到的泄漏。

This is not the kind of a leak that you need to worry about. 这不是您需要担心的泄漏。 It is rather annoying, and makes debugging difficult, true. 这确实很烦人,并且使调试变得困难,真实。

In the past, I took one approach in a framework class library that I wrote some time ago. 过去,我在一段时间前编写的框架类库中采用了一种方法。 I did not use detached threads at all, but all threads were joinable threads. 我根本没有使用分离线程,但是所有线程都是可连接线程。 The framework started one singleton background thread whose only job was to join() the terminated threads. 该框架启动了一个单例后台线程,其唯一的工作就是join()终止的线程。 Then, each thread started by the framework will queue up its own thread id for the singleton background thread, just before each thread terminates. 然后,由框架启动的每个线程将在每个线程终止之前,将其自己的线程ID排队给单例后台线程。

The net effect was equivalent to detached threads. 最终效果等同于分离的线程。 I could start each thread and not worry about joining to it. 我可以启动每个线程,而不必担心加入它。 It's going to be the background thread's job. 这将是后台线程的工作。 The framework would signal the background thread to terminate itself, and join it, before exiting. 该框架将发出信号,通知后台线程在退出之前终止自身并加入它。 So, if all goes well, there will not be any reported memory leaks that can be accounted to thread support. 因此,如果一切顺利,将不会有任何报告的内存泄漏可归因于线程支持。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM