很多人以为句柄就是指针,实际上句柄并不是那么简单的概念。
38.什么是句柄
句柄在Windows编程中是一个很重要的概念,在很多程序中扮演着重要的角色。在Windows环境中,句柄是用来标识项目的,这些项目包括:
1.模块(module)
2.任务(task)
3.实例(instance)
4.文件(file)
5.内存块(block of memory)
6.菜单(menu)
7.控制(control)
8.字体(font)
9.资源(resource)(包括图标(icon),光标(cursor),字符串(string)等
10.GDI对象(GDI object)(包括位图(bitmap),画刷(brush),元文件(metafile))、调色板(palette)、画笔(pen)、区域(region)以及设备描述表(device context)。
Windows是以虚拟内存为基础的操作系统。在这种操作系统下,Windows内存管理器在内存中来回移动对象,从而满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。由于地址总是如此变化,所以Windows操作系统为各应用程序腾出一些内存存储地址空间,又称为句柄地址空间,专门用来登记各应用对象在内存中的地址变化,而这些地址空间(存储单元的位置)本身是不变的。Windows内存管理器在内存中移动对象的位置后,把对象新的地址放在句柄地址空间来保存。这样只要记住这个句柄地址空间的地址就可以间接地知道对象在内存中的具体位置。这个地址空间在对象装载(Load)时由系统分配,当系统卸载是(Unload)又释放给系统。
因此Windows程序中并不是用物理地址来标识内存块、文件、任务的。Windows API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。
在Windows编程中会用到大量的句柄,比如:HINSTANCE(实例句柄),HBITMAP(位图句柄),HDC(设备描述表句柄),HICON(图标句柄)等,其中还有一个通用的句柄,就是HANDLE,如下语句:
HINSTANCE hInstance;
HANDLE hInstance;
程序执行顺序是:句柄地址(稳定)-> 记载对象在内存中的地址->对象在内存中的地址(不稳定)->实际对象。但是程序每次重新启动,系统分配给程序的句柄并不一定还是原来的句柄,而且绝大多数情况下是不一样的。
39.指针与句柄有什么区别?
指针对应着数据在内存中的地址,利用指针可以自由地修改数据。Windows并不希望一般程序修改其内部数据结构,因为这样太不安全。所以Windows给每个使用GlobalAlloc等函数声明的内存区域指定一个句柄,即指向指针的指针。句柄和指针都是地址,不同之处在于:
1.句柄可以指向一个复杂的结构,并且可以与系统有关,例如线程的句柄,它可以指向一个类或者结构,而且和系统有很密切的关系,当一个线程由于不可预料的原因而终止时,系统就可以返回它所占用的资料,如CPU、内存等。
2.指针也可以指向一个复杂的结构,但是通常是由用户自行定义,所以必要的工作要由用户完成,特别删除部分的工作。