• TerminateThread危险


    TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:

    • If the target thread owns a critical section, the critical section will not be released.(未释放互斥区,造成死锁)
    • If the target thread is allocating memory from the heap, the heap lock will not be released.(未释放堆分配锁,造成死锁)
    • If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread’s process could be inconsistent.(在执行内核函数时退出,造成该线程所在进程状态不确定,程序可能崩溃)
    • If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.(在使用DLL时退出,造成DLL被销毁,其他使用该DLL得程序可能出现问题!)

    A thread cannot protect itself against TerminateThread, other than by controlling access to its handles. The thread handle returned by the CreateThread and CreateProcess functions has THREAD_TERMINATE access, so any caller holding one of these handles can terminate your thread.

    听过无数次不要TerminateThread,只是工作中常用,貌似也没有什么问题。今天在高强度测试中发现了一个不可原谅的错误。参看下面的例子


    DWORD __stdcall mythread(void* )
    {
        while( true )
        {
            char* p = new char[1024];

            delete p;
        }
    }


    int _tmain(int argc, _TCHAR* argv[])
    {

        HANDLE h = CreateThread(NULL, 0, mythread, NULL, 0, NULL);

        Sleep(1000);

        TerminateThread(h, 0);
        h = NULL;

        char* p = new char[1024]; //这里会死锁,过不去 

        delete []p;

        return 0;
    }

    为什么死锁呢?new操作符用的是小块堆,整个进程在分配和回收内存时,都要用同一把锁。如果一个线程在占用该锁时被杀死(即临死前该线程在new或delete操作中),其他线程就无法再使用new或delete了,表现为hang住。

    《核心编程》里明确提醒不要TerminateThread,但原因并不是血淋淋滴。今天发现的这个bug印证了此书的价值。

    另注:许多临时的网络操作经常用TerminateThread,作为网络不通时的退出机制,以后要改改了。比如让该线程自生自灭,自行退出。

  • 相关阅读:
    接口和抽象类的异同点
    实体对象间传值克隆
    什么是反射&反射的8个类的用法
    ERP中反射的两个实例
    基础02 Java 跨平台原理
    基础01 dos命令
    lists删除
    多字段 java对象排序
    Java对象排序
    MySQL表中数据的迁移
  • 原文地址:https://www.cnblogs.com/kex1n/p/2757536.html
Copyright © 2020-2023  润新知