内存泄漏使用Windows ThreadPool API

时间:2012-12-04 14:47:53

标签: threadpool

我在我的应用程序中使用Windows ThreadPools,并且每次调用CreateThreadPoolWork()时都会遇到136字节的内存泄漏,如UMDH所示:

+ 1257728 ( 1286424 -  28696)   9459 allocs BackTraceB0035CC
+    9248 (   9459 -    211)    BackTraceB0035CC    allocations

    ntdll!RtlUlonglongByteSwap+B52
    ntdll!TpAllocWork+8D
    KERNEL32!CreateThreadpoolWork+25
    ... My Code ...

我正在使用清理组,因此根据文档我没有调用CloseThreadPoolWork()。

我处理ThreadPool的代码是:

typedef PTP_WORK ThreadHandle_t;
typedef PTP_WORK_CALLBACK THREAD_ENTRY_POINT_T;

static PTP_POOL pool = NULL;
static TP_CALLBACK_ENVIRON CallBackEnviron;
static PTP_CLEANUP_GROUP cleanupgroup = NULL;

int mtInitialize()
{
    InitializeThreadpoolEnvironment(&CallBackEnviron);

    pool = CreateThreadpool(NULL);

    if (NULL == pool)
    {
        return -1;
    }

    cleanupgroup = CreateThreadpoolCleanupGroup();

    if (NULL == cleanupgroup)
    {
        return -1;
    }

    SetThreadpoolCallbackPool(&CallBackEnviron, pool);

    SetThreadpoolCallbackCleanupGroup(&CallBackEnviron, cleanupgroup, NULL);

    return 0; // Success
}

void mtDestroy()
{
    CloseThreadpoolCleanupGroupMembers(cleanupgroup, FALSE, NULL);
    CloseThreadpoolCleanupGroup(cleanupgroup);
    DestroyThreadpoolEnvironment(&CallBackEnviron);
    CloseThreadpool(pool);
}

//Create thread
ThreadHandle_t mtRunThread(THREAD_ENTRY_POINT_T entry_point, void *thread_args)
{
    PTP_WORK work = NULL;

    work = CreateThreadpoolWork(entry_point, thread_args, &CallBackEnviron);

    if (NULL == work) {
        // CreateThreadpoolWork() failed.
        return 0;
    }

    SubmitThreadpoolWork(work);

    return work;
}

//Wait for a thread to finish
void mtWaitForThread(ThreadHandle_t thread)
{
    WaitForThreadpoolWorkCallbacks(thread, FALSE);
}

我做错了吗? 我为何泄漏记忆的任何想法?

1 个答案:

答案 0 :(得分:0)

考虑到你的评论,我猜你已经弄明白了,但问题是你只能在CloseThreadpoolCleanupGroupMembers()中拨打mtDestroy()

如果你有一个持久的线程池,除非你定期调用CloseThreadpoolCleanupGroupMembers(),否则不会释放内存。您的代码和注释表明您可以这样做,但如果没有负责创建和销毁线程池的代码,我无法确认。

我对持久线程池的建议是在回调函数中调用CloseThreadpoolWork()。如果您正在创建和销毁线程池,Microsoft的建议会更好,但如果您在应用程序的生命周期内维护一个线程池,则CloseThreadpoolWork()比定期调用CloseThreadpoolCleanupGroupMembers()更简单,更容易。

顺便说一句,只要您告诉CloseThreadpoolCleanupGroupMembers()取消任何待处理的回调(将fCancelPendingCallbacks传递为TRUE)以确保CloseThreadpoolWork()被调用,就可以安全地执行这两项操作在任何清理过的工作项目上:

  

您只能通过关闭它来撤销工作对象的成员身份   可以使用CloseThreadpoolWork在个人基础上完成   功能。线程池知道工作对象是其成员   清理组并在关闭之前撤销其成员资格。这个   确保清理组时应用程序不会崩溃   后来试图关闭其所有成员。反之亦然:如果   您首先指示清理组关闭其所有成员   然后在现在无效的工作对象上调用CloseThreadpoolWork   应用程序将崩溃。

来自Windows with C++ - Thread Pool Cancellation and Cleanup