[例8.3] TermiateThread结束线程导致死锁

书籍:《Visual C++ 2017从入门到精通》的2.3.8 Win32控件编程

环境:visual studio 2022

创建控制台工程Test803

编写代码Test803.cpp

// Test803.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <Windows.h>


//这段代码演示了 ​​多线程环境下强制终止线程的风险​​,包含以下关键部分:
//​​子线程​​:无限循环中频繁分配和释放内存(new[] / delete[])。
//​​主线程​​:创建子线程后休眠1.5秒,调用 TerminateThread 强制终止子线程,随后自行分配和释放内存。

DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
    char* p;

    /*子线程的无限循环​
        CPU占用率过高​​:无限循环导致CPU资源被持续占用(约100% ),程序无响应。
        ​​内存碎片​​:频繁分配 / 释放小内存块(5字节)可能加剧内存碎片化,影响性能。*/
    while (1)
    {
        p = new char[5];
        delete[]p;
    }
}

int main()
{
    HANDLE h;
    char* q;

    h = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
    Sleep(1500);

    /* TerminateThread 的危险性​​
        ​​强制终止线程​​:
        TerminateThread(h, 0) 会立即终止子线程,​​不执行任何清理操作​​(如释放锁、调用DLL分离函数)。
        ​​资源泄漏风险​​:
        子线程可能在 new[] 或 delete[] 过程中被终止,导致内存泄漏或堆损坏。
        若子线程持有临界区锁或操作共享DLL,主线程后续操作可能引发死锁或未定义行为。*/
    TerminateThread(h, 0);


    /*主程序执行到"q = new char[2];"时将停滞不前,这是因为子线程中用了new/delete操作符向系统申请和释放对空间,
        进程在其分配内存和回收空间时都会用到同一把锁。如果该线程在占用(被杀死之前正在new/delete操作)这把锁期间被杀死,
        其他线程就无法再进行new/delete操作了,因为该锁一直在占用中。*/
    
    /*主线程的内存操作
        潜在堆损坏​​:若子线程被终止时正在修改堆结构,主线程的内存分配可能失败或崩溃。*/
    q = new char[2];
    printf("分配成功\n");

    delete[]q;

    CloseHandle(h);

    return 0;
}

编译执行效果

程序卡死,原因分析请查看代码注释。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值