书籍:《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;
}
编译执行效果
程序卡死,原因分析请查看代码注释。