- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我创建了创建两个线程的简单测试;第一个 (WorkerThreadFun) 执行无限循环,第二个 (WorkerGuardThreadFun) 以小超时终止它。
要终止的线程似乎没有进行显式分配(至少在 WorkerThreadFun 内部)并且只使用普通 C 类型的堆栈变量,所以我希望堆栈将被 TerminateThread< 释放/em>() 与 CloseHandle()。
由于某种原因,此测试会泄漏我的 Win7 上的内存。
堆分配不平衡在哪里?
#include <windows.h>
#include <synchapi.h>
#include <assert.h>
#include <stdio.h>
#define STK_SIZE 4097
typedef enum
{
GRD_IDLE,
GRD_READY,
GRD_TASKSTARTING,
GRD_TASKWAITING
} GuardThreadState;
typedef struct
{
HANDLE mHworkerThread;
HANDLE mHworkerGroupThread;
volatile int mIsWorkerStarted;
GuardThreadState mGuardThreadState;
CRITICAL_SECTION mLock;
CONDITION_VARIABLE mThreadReadyCond;
CONDITION_VARIABLE mStartTaskCond;
CONDITION_VARIABLE mTaskFinishedCond;
} WorkerThreadHolder;
/*
typedef VOID(WINAPI *PRtlFreeUserThreadStack)(HANDLE hProcess, HANDLE hThread);
static PRtlFreeUserThreadStack RtlFreeUserThreadStack = NULL;
*/
DWORD WINAPI WorkerThreadFun(_In_ LPVOID p);
DWORD WINAPI WorkerGuardThreadFun(_In_ LPVOID p);
void Start(WorkerThreadHolder *workerThreadHolderPtr);
void ExecuteTask(WorkerThreadHolder *workerThreadHolderPtr);
/*----------------------------------------------------------------------------*/
DWORD WINAPI WorkerThreadFun(_In_ LPVOID p)
{
/* use stack variables only in this thread in hope the stack will be deallocated by TerminateThread() */
WorkerThreadHolder *workerThreadHolderPtr = (WorkerThreadHolder *)p;
volatile int i;
workerThreadHolderPtr->mIsWorkerStarted = 1;
/*WakeAllConditionVariable(&workerThreadHolderPtr->mThreadReadyCond);*/
/* do nothing for infinite long time */
for(i = 0;; ++i)
i = i;
/*WakeAllConditionVariable(&workerThreadHolderPtr->mTaskFinishedCond);*/
return 0;
}
DWORD WINAPI WorkerGuardThreadFun(_In_ LPVOID p)
{
const DWORD taskExecutionTimeoutInMillisec = 1;
WorkerThreadHolder *workerThreadHolderPtr = (WorkerThreadHolder *)p;
EnterCriticalSection(&workerThreadHolderPtr->mLock);
workerThreadHolderPtr->mGuardThreadState = GRD_READY;
WakeAllConditionVariable(&workerThreadHolderPtr->mThreadReadyCond);
for (;;)
{
for (;;)
{
SleepConditionVariableCS(
&workerThreadHolderPtr->mStartTaskCond,
&workerThreadHolderPtr->mLock,
INFINITE);
if (workerThreadHolderPtr->mGuardThreadState == GRD_TASKSTARTING)
break;
}
workerThreadHolderPtr->mGuardThreadState = GRD_TASKWAITING;
{
BOOL isTaskFinishedOk = FALSE;
for (;;)
{
isTaskFinishedOk =
SleepConditionVariableCS(
&workerThreadHolderPtr->mTaskFinishedCond,
&workerThreadHolderPtr->mLock,
taskExecutionTimeoutInMillisec);
if (!isTaskFinishedOk)
break;
}
if (isTaskFinishedOk)
{
/* never happens in this test */
}
else
{
BOOL isClosed;
TerminateThread(workerThreadHolderPtr->mHworkerThread, 0);
/*if (RtlFreeUserThreadStack != NULL)
RtlFreeUserThreadStack(GetCurrentProcess(), workerThreadHolderPtr->mHworkerThread);*/
isClosed = CloseHandle(workerThreadHolderPtr->mHworkerThread);
workerThreadHolderPtr->mIsWorkerStarted = 0;
workerThreadHolderPtr->mHworkerThread =
CreateThread(
NULL,
STK_SIZE,
WorkerThreadFun,
(PVOID)workerThreadHolderPtr,
STACK_SIZE_PARAM_IS_A_RESERVATION,
NULL);
}
}
workerThreadHolderPtr->mGuardThreadState = GRD_READY;
WakeAllConditionVariable(&workerThreadHolderPtr->mThreadReadyCond);
}
return 0;
}
void Start(WorkerThreadHolder *workerThreadHolderPtr)
{
workerThreadHolderPtr->mGuardThreadState = GRD_IDLE;
workerThreadHolderPtr->mIsWorkerStarted = 0;
InitializeConditionVariable(&workerThreadHolderPtr->mThreadReadyCond);
InitializeConditionVariable(&workerThreadHolderPtr->mStartTaskCond);
InitializeConditionVariable(&workerThreadHolderPtr->mTaskFinishedCond);
InitializeCriticalSection(&workerThreadHolderPtr->mLock);
workerThreadHolderPtr->mHworkerThread =
CreateThread(
NULL,
STK_SIZE,
WorkerThreadFun,
(LPVOID)workerThreadHolderPtr,
STACK_SIZE_PARAM_IS_A_RESERVATION,
NULL);
workerThreadHolderPtr->mHworkerGroupThread =
CreateThread(
NULL,
0,
WorkerGuardThreadFun,
(LPVOID)workerThreadHolderPtr,
0,
NULL);
}
void ExecuteTask(WorkerThreadHolder *workerThreadHolderPtr)
{
assert(workerThreadHolderPtr->mHworkerThread != NULL);
assert(workerThreadHolderPtr->mHworkerGroupThread != NULL);
EnterCriticalSection(&workerThreadHolderPtr->mLock);
for (;;)
{
if (workerThreadHolderPtr->mGuardThreadState == GRD_READY /* && workerThreadHolderPtr->mIsWorkerStarted != 0 */)
break;
SleepConditionVariableCS(
&workerThreadHolderPtr->mThreadReadyCond,
&workerThreadHolderPtr->mLock,
INFINITE);
}
/* just poll */
for (;;)
{
if (workerThreadHolderPtr->mIsWorkerStarted != 0)
break;
}
workerThreadHolderPtr->mGuardThreadState = GRD_TASKSTARTING;
WakeAllConditionVariable(&workerThreadHolderPtr->mStartTaskCond);
LeaveCriticalSection(&workerThreadHolderPtr->mLock);
}
/*----------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
int i;
WorkerThreadHolder workerThreadHolder;
/*
HMODULE NTLibrary = GetModuleHandleW(L"ntdll.dll");
RtlFreeUserThreadStack = (PRtlFreeUserThreadStack)GetProcAddress(NTLibrary, "RtlFreeUserThreadStack");
*/
Start(&workerThreadHolder);
for(i = 0;; ++i)
{
ExecuteTask(&workerThreadHolder);
printf("%d Execution started...\n", i);
/*fflush(stdout);*/
}
return 0;
}
使用 Visual Studio 2015 测试,vc 命令行:/GS-/analyze-/W3/Zc:wchar_t/ZI/Gm/Od/Fd"Debug\vc140.pdb"/Zc:inline/fp:precise/D "WIN32"/D "_DEBUG"/D "_CONSOLE"/D "_UNICODE"/D "UNICODE"/errorReport:prompt/WX-/Zc:forScope/Gd/Oy/MDd/Fa"Debug\"/nologo/Fo"Debug\"/Fp"Debug\ConsoleApplication1.pch"
链接器:/OUT:"C:\Users\cherney\documents\visual studio 2015\Projects\ConsoleApplication1\Debug\ConsoleApplication1.exe"/MANIFEST/NXCOMPAT/PDB:"C:\Users\cherney\documents\visual studio 2015\Projects\ConsoleApplication1\Debug\ConsoleApplication1.pdb"/DYNAMICBASE "kernel32.lib""user32.lib""gdi32.lib""winspool.lib""comdlg32.lib""advapi32.lib""shell32.lib""ole32.lib""oleaut32.lib""uuid.lib""odbc32.lib""odbccp32.lib"/DEBUG/MACHINE:X86/INCREMENTAL/PGD:"C:\Users\cherney\documents\visual studio 2015\Projects\ConsoleApplication1\Debug\ConsoleApplication1.pgd"/SUBSYSTEM:CONSOLE/MANIFESTUAC:"level='asInvoker' uiAccess='false'"/ManifestFile:"Debug\ConsoleApplication1.exe.intermediate.manifest"/ERRORREPORT:PROMPT/NOLOGO/TLBID:1
最佳答案
“TerminateThread”是“危险的”,实际上可能不会发生某些取消分配(参见 https://learn.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-terminatethread )。最好重新设计代码以在不使用“TerminateThread”的情况下干净地退出线程。
关于c++ - TerminateThread() with CloseHandle() on thread which uses only stack plain variables (without alloc) 泄漏内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54821048/
我有一个应用程序,它通过 SetConsoleCtrlHandler 注册了句柄例程。事情是中断信号我必须在退出前做一些清理,这就是问题开始的时候。因为,其他线程继续运行并使用一些应该释放的资源,我在
所以我一直在学习 Windows API 中的线程,我写了一些测试代码,但我遇到了一些问题。首先我有两个功能: DWORD WINAPI MyThreadFunction( LPVOID lpPara
如何释放调用 TerminateThread 后剩余的虚拟内存?可以通过 VirtualFree 完成吗?当然如何。我完全理解 TerminateThread 的“危险”。 最佳答案 在非托管进程中,
我有一个使用 CreateThread 函数创建的 ThreadA。在 ThreadA 内部,另一个线程 ThreadB 是使用 CreateThread 函数创建的。 现在,我想从 ThreadA
如果我在 Windows 上使用 TerminateThread 终止线程函数,该线程是在函数返回后实际终止还是异步终止? 最佳答案 定义“实际终止”。文档说该线程不能再执行任何用户模式代码,如此有效
我的应用程序创建了一个线程并一直在后台运行。我只能手动终止线程,不能从线程回调函数中终止。目前我正在使用 TerminateThread() 来终止该线程,但它有时会导致它挂起。我知道有一种方法可以使
调用TerminateThread时,即使线程处于挂起状态,线程也会终止吗? 最佳答案 TerminateThread function销毁线程而不考虑其状态或可能的副作用。链接的 MSDN 页面对此
我使用 CreateThread 然后使用 TerminateThread 来取消线程。看起来堆栈空间仍然被分配。有办法解决这个问题吗?我没有使用任何形式的动态内存调用,例如 malloc/new。线
由于restrictions on DllMain(我知道这对DLL中的全局和静态对象构造函数和析构函数同样适用),像带异步文件写入/刷新线程的单例记录器这样的简单事情变得太棘手了。单例记录器位于DL
我有这个代码需要使用,但阻碍我的是 here它说 TerminateThread 适用于:仅桌面应用程序。我想知道是否可以在 azure Worker 角色中使用此代码,特别是在我用来运行 Worke
我有这个代码需要使用,但阻碍我的是 here它说 TerminateThread 适用于:仅桌面应用程序。我想知道是否可以在 azure Worker 角色中使用此代码,特别是在我用来运行 Worke
这个问题在这里已经有了答案: How to get the winapi id of a thread that has been created using the standard librar
如果我从 C++ 代码调用 TerminateThread,那么稍后我会收到 FatalExecutionEngineError MDA。该错误主要发生在我对字符串执行不同的操作(即 concat)时
我创建了创建两个线程的简单测试;第一个 (WorkerThreadFun) 执行无限循环,第二个 (WorkerGuardThreadFun) 以小超时终止它。 要终止的线程似乎没有进行显式分配(至少
我是一名优秀的程序员,十分优秀!