记录一次句柄泄露溯源

引言

偶然间在任务管理器中发现之前写的程序(KMUCounter)句柄很高,众所周知,句柄就相当于一个索引,如果持续增长可能导致程序句柄达到上限影响稳定性,并且影响系统性能。
image.png

解决过程

首先观察变化趋势,发现是每秒增加1,在代码中找相关的计时器,找了找也没发现什么问题,因为时间是动态设置的,所以也不太好找。(主要是没耐心了),谁想到黑盒更直观的找到了问题。
准备windbg,附加到进程上,开启句柄追踪堆栈(!htrace -enable),放行之后等一会儿然后再暂停,执行!htrace -diff,查看差异,虽然有很多,但是基本上都是重复的,发现存在OpenProcess,这就使我警觉起来,因为打开进程肯定会创建句柄,如果不销毁的话,那就会越聚越多。
image.png

回看那部分代码部分,果然没有CloseHandle,加上重新编译,解决问题。

需要警惕的方法

一、Windows 原生 API(必须手动释放)

CreateFile → CloseHandle 或 CloseHandle(文件句柄)。

OpenProcess → CloseHandle(打开进程)。

CreateThread / CreateRemoteThread → CloseHandle(创建线程)

CreateProcess → PROCESS_INFORMATION.hProcess / hThread 都要 CloseHandle。

CreateFileMapping → UnmapViewOfFile + CloseHandle(mapping)`。

FindFirstFile → FindClose(查文件)

GetDC(hWnd) → ReleaseDC(hWnd, hdc)

CreateCompatibleDC → DeleteDC

CreateCompatibleBitmap / CreateBitmap / CreateDIBSection → DeleteObject

SelectObject(hdc, hOld) → 在删除位图等 GDI 对象前要 SelectObject 恢复旧对象(否则不能删除)

LoadLibrary → FreeLibrary(DLL 引用计数)

OpenEvent, OpenSemaphore → CloseHandle

二、GDI / USER 相关(图形/窗口句柄)

CreatePen, CreateBrush, CreateFont, CreateBitmap, CreateCursor, CreateIcon → DeleteObject / DestroyCursor / DestroyIcon`

GetWindowTextBuffer(分配内存)注意释放你自己分配的内存。

三、网络 / 套接字 / Winsock

socket() → closesocket()

WSAStartup() → WSACleanup()(匹配)

四、文件 / C 运行时

fopen() → fclose()

fread/fwrite 最后需要 fclose / fflush

std::ifstream/ofstream:确保析构或 close()

结语

在使用这种需要手动管理内存的语言时,内存管理上需要留意。

评论 0

还没有评论,来说点什么吧。

提交后需要审核才会公开。