我在我的应用程序中使用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);
}
我做错了吗? 我为何泄漏记忆的任何想法?
答案 0 :(得分:0)
考虑到你的评论,我猜你已经弄明白了,但问题是你只能在CloseThreadpoolCleanupGroupMembers()
中拨打mtDestroy()
。
如果你有一个持久的线程池,除非你定期调用CloseThreadpoolCleanupGroupMembers()
,否则不会释放内存。您的代码和注释表明您可以这样做,但如果没有负责创建和销毁线程池的代码,我无法确认。
我对持久线程池的建议是在回调函数中调用CloseThreadpoolWork()
。如果您正在创建和销毁线程池,Microsoft的建议会更好,但如果您在应用程序的生命周期内维护一个线程池,则CloseThreadpoolWork()
比定期调用CloseThreadpoolCleanupGroupMembers()
更简单,更容易。
顺便说一句,只要您告诉CloseThreadpoolCleanupGroupMembers()
取消任何待处理的回调(将fCancelPendingCallbacks
传递为TRUE
)以确保CloseThreadpoolWork()
被调用,就可以安全地执行这两项操作在任何清理过的工作项目上:
您只能通过关闭它来撤销工作对象的成员身份 可以使用CloseThreadpoolWork在个人基础上完成 功能。线程池知道工作对象是其成员 清理组并在关闭之前撤销其成员资格。这个 确保清理组时应用程序不会崩溃 后来试图关闭其所有成员。反之亦然:如果 您首先指示清理组关闭其所有成员 然后在现在无效的工作对象上调用CloseThreadpoolWork 应用程序将崩溃。