3

アプリケーションでWindowsThreadPoolsを使用していますが、UMDHで確認できるように、CreateThreadPoolWork()を呼び出すたびに136バイトのメモリリークが発生しています。

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

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

Cleanup Groupを使用しているので、ドキュメントによると、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);
}

私は何か間違ったことをしていますか?なぜ私がメモリリークしているのか、何か考えはありますか?

4

1 に答える 1

0

あなたのコメントを考えると、あなたはそれを理解したと思いますが、問題はあなたCloseThreadpoolCleanupGroupMembers()mtDestroy().

永続的なスレッド プールがある場合、CloseThreadpoolCleanupGroupMembers()定期的に呼び出さない限り、メモリは解放されません。あなたのコードとコメントはあなたがそうしていることを示唆していますが、スレッドプールの作成と破棄を担当するコードなしではこれを確認できません。

永続的なスレッド プールに対する私の推奨事項はCloseThreadpoolWork()、コールバック関数を呼び出すことです。スレッド プールを作成および破棄する場合は、Microsoft の推奨事項が適切に機能しますが、アプリケーションの存続期間中に 1 つのスレッド プールを維持する場合はCloseThreadpoolWork()、定期的に呼び出すよりも単純で簡単です。CloseThreadpoolCleanupGroupMembers()

ところで、CloseThreadpoolCleanupGroupMembers()保留中のコールバックをキャンセルする ( fCancelPendingCallbacksas として渡すTRUE) ように指示する限り、両方を実行しても安全ですCloseThreadpoolWork()

作業オブジェクトのメンバーシップを取り消すには、作業オブジェクトを閉じる必要があります。これは、CloseThreadpoolWork 関数を使用して個別に行うことができます。スレッド プールは、作業オブジェクトがクリーンアップ グループのメンバーであることを認識し、それを閉じる前にそのメンバーシップを取り消します。これにより、後でクリーンアップ グループがすべてのメンバーを閉じようとしたときに、アプリケーションがクラッシュしなくなります。逆は正しくありません。最初にクリーンアップ グループにすべてのメンバーを閉じるように指示し、次に無効になった作業オブジェクトで CloseThreadpoolWork を呼び出すと、アプリケーションがクラッシュします。

C++ を使用した Windowsから- スレッド プールのキャンセルとクリーンアップ

于 2016-06-17T02:40:51.843 に答える