找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 4047|回复: 1

句柄泄露的检测和处理

[复制链接]
发表于 2014-7-1 17:18:12 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
     句柄泄露,大家可能比较陌生,事实上这个词是Handle Leak,无论用中文还是英文搜索引擎,都很难发现他的踪迹(事实上正因为没人写过我才要写出来),而他的同胞兄弟Memoery Leak即内存泄漏,则是老生常谈了,事实上他们二者很相近。内存泄漏是指利用windows内存管理器分配了内存,使用结束之后,没有进行释放操作(或者只释放了一部分),典型的做法是new而不delete,malloc不free,这样,会浪费系统的内存空间。对于应用层程序,结束后系统都会相应的回收资源,然而对于驱动程序和服务,就不太明智了,因为他们一直驻留,很容易出现蓝屏死机的问题。而句柄泄露,众所周知,为了避免使用指针这种太灵活的工具而造成不良后果(任意写数据)增加稳定性,windows采用句柄这种东西来代替指针的使用,HBITMAP位图句柄、HBRUSH画刷句柄、HCURSOR光标句柄、HDC图形设备句柄、HFILE文件句柄、HKEY注册表键句柄、HMODULE模块句柄,等等很多。如果你细心观察,看看HANDLE的定义,会发现winnt.h中是这样的:
typedef void *HANDLE;
#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
那么DECLARE_HANDLE(HPEN)就是
struct HPEN__
{
  int unused;
|
typedef struct HPEN__ *HPEN; 也就是说HPEN是个指针,指向一个32位整形数据unused。
句柄是在整个进程唯一标识某资源的32位值,而指针则是很灵活的,可以指向对象,结构体和普通数据,多个指针可以指向一个对象,其位数则与系统和编译环境有关。
指针所对应的虚拟内存地址是固定的,因为值就代表虚拟内存地址,所以如果分配空间不够就需要手动释放并重新分配。
句柄所确定的对象的位置则是可能发生变动的,变动以后,他内部实现相应的“指针”自然要变,但是这个是操作系统自动处理的,你所能用的仅仅有句柄而已,句柄值是不变的。最明显的例子是GloalAlloc,其参数可以设置为固定内存和可移动内存。不过,应该说很多情况下,句柄值就是指针,GlobalAlloc刚分配的时候,返回的HGLOBAL是可以当做指针来用的。
句柄也可以是非指针和无意义的值,比如-1,或者纯粹是某个整形值,比如CreateFile返回值

句柄一般指向的结构体和对象都是成员较多,较为庞大的,ObReferenceObjectByHandle这个内核函数就是用来把对象句柄(注意只是对象句柄)转换为指针的

和指针一样,如果在获取了句柄而不关闭的话,会产生句柄泄露,句柄泄露理论上说其实也是内存泄露的一个分支了,只不过泄露的代码会在win内核,而不是用户代码中。
同样,当用户进程结束后,系统会自动回收资源,句柄所对应内存资源也会得到释放,然而对于服务程序和驱动,则是个灾难。现在程序员们对于内存泄露的严重性很清楚,
而对于句柄泄露却没那么敏感,当时我做保密检查工具的时候就有这个感慨(智能指针都有AutoPtr,是不是应该做个智能句柄出来?AutoHandle<HFONT>)。
当程序出现大量句柄泄露时,你可以用过任务管理器或者性能分析工具分析出来,查看->选择列->句柄数
在windbg中检测这类错误使用的是!htrace,有兴趣的可以自行学习。


回复

使用道具 举报

发表于 2014-7-1 18:58:24 | 显示全部楼层
用GetDC而不使用ReleaseDC,会直接导致窗口无法绘图。小学的时候我编写一款屏幕截图工具就是这样的效果。
回复 赞! 靠!

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-12-23 01:42 , Processed in 0.038202 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表