2012-12-04 129 views
2

我使用Windows線程池在我的應用程序,和我遇到的136個字節每次調用CreateThreadPoolWork(內存泄漏),通過UMDH所看到:內存泄漏使用Windows線程池API

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

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

我使用清理組,所以根據文檔我沒有調用CloseThreadPoolWork()。

我處理的線程池代碼:

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

難道我做錯了什麼? 任何想法,爲什麼我泄漏內存?

+0

閱讀MSDN上的一篇文章(http://msdn.microsoft.com/en-us/magazine/hh456398.aspx),我看到一個評論:「如果你不叫CloseThreadpoolCleanupGroupMembers ,你的應用程序會泄漏內存。「 在我的代碼中,我只在應用程序的最後調用了這個函數。那麼,這將解釋內存泄漏? – user1875971

回答

0

我猜你已經想通了,給出你的評論,但問題是,你只能撥打在mtDestroy()

如果您有一個持久線程池,除非定期調用CloseThreadpoolCleanupGroupMembers(),否則內存將不會被釋放。您的代碼和評論意味着您可以這樣做,但如果沒有負責創建和銷燬線程池的代碼,我無法確認這一點。

我對持久線程池的建議是在回調函數中調用CloseThreadpoolWork()。如果您創建和銷燬線程池,則微軟的建議會更好,但如果您在應用程序的整個生命週期中維護一個線程池,則CloseThreadpoolWork()比定期調用CloseThreadpoolCleanupGroupMembers()更簡單,更容易。

順便說一句,它是安全的,只要你告訴CloseThreadpoolCleanupGroupMembers()取消了所有待回調做兩件事(通過fCancelPendingCallbacksTRUE),以確保CloseThreadpoolWork()被稱爲上的任何清理工作項目:

你可以只有通過關閉工作對象的成員資格才能撤銷工作對象的成員資格,可以使用CloseThreadpoolWork 函數單獨完成該工作對象的成員資格。線程池知道工作對象是清理組的成員,並在關閉它之前撤銷其成員資格。此 可確保當清理組 稍後嘗試關閉其所有成員時,應用程序不會崩潰。反之亦然:如果您首先指示清理組關閉其所有成員,然後在現在無效的工作對象上調用CloseThreadpoolWork,則您的 應用程序將崩潰。

Windows with C++ - Thread Pool Cancellation and Cleanup