zoukankan      html  css  js  c++  java
  • 句柄与指针的区别(一)

    内存句柄与指针的区别

        句柄其实就是指针,但是他和指针最大的不同是:给你一个指针,你可以通过这个指针做任何事情,也许是好事,也许是通过这个指针破坏内存,干一些捣乱的事情。这个我想大家都会碰到过,因为乱用指针导致程序崩溃
        句柄就没有这个缺点,通过句柄,你只能干一些windows让你干的事情(调用一些api函数等等),没有了指针的坏处。

        句柄是一些表的索引也就是指向指针的指针,句柄和指针都是地址,句柄是Windows编程的一个关键性的概念,编写Windows应用程序总是要和各种句柄打交道。
        所谓句柄,就是一个唯一的数,用以标识许多不同的对象类型,如窗口、菜单、内存、画笔、画刷等。在Win32里,句柄是指向一个“无类型对象”(void*)的指针,也就是一个4字节长的数据。
        无论它的本质是什么,句柄并不是一个真正意义上的指针。从构造上看,句柄是一个指针,尽管它没有指向用于存储某个对象的内存位置。事实上,句柄指向一个包含了对该对象进行的引用的位置。
        句柄的声明是这样的:
        typedef void *HANDLE
        由于Windows是一个多任务操作系统,它可以同时运行多个程序或一个程序的多个副本。这些运行的程序称为一个实例。为了对同一程序的多个副本进行管理,Windows引入了实例句柄。Windows为每个应用程序建立一张表,实例句柄就好象是这张表的一个索引。
        不同在于:
          1、句柄所指的可以是一个很复杂的结构,并且很有可以是与系统有关的,比如说上面所说的线程的句柄,它指向的就是一个类或者结构,他和系统有很密切的关系,当一个线程由于不可预料的原因,而终止时在系统就可以回它所占用的资料,如CPU,内存等等,反过来想可以知道,这个句柄中的某一些项,是与系统进行交互的。由于Windows系统,是一个多任务的系统,它随时都可能要分配内存,回收内存,重组内存。
          2、指针它也可以指向一个复杂的结构,但是通常是用户定义的,所以的必需的工作都要用户完成,特别是在删除的时候。但在VC++6.0中也有一些指针,它们都是处理一些小问题才用的,如最常见的字符的指针,它也是要用户处理的如果你动态分配了内存;但是Cstring 就不要用户处理了,它其实是VC++中的一个类,所以的操作都由成员函数完成,产生(分配)由构造函数,删除(回收)由析构函数完成。


    获得窗口句柄三种方法

    .HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName)

    HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter,LPCTSTR lpClassName, LPCTSTR lpWindowName)

    2.HWND WindowFromPoint(POINT& Point)//获得当前鼠标光标位置的窗口HWND

    3.BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)

    BOOL CALLBACK EnumChildWindows(HWND hWndParent, WNDENUMPROC lpEnumFunc,LPARAM lParam)
    BOOL CALLBACK EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
    BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)

    指针 句柄之间的转换

    a.由指针获得句柄
    CWnd * pWnd;
    CWnd HWnd;
    HWnd = pWnd->GetSafeHWnd();

    b.由句柄得到指针:
    CWnd* pWnd=FromeHandle(hMyHandle);
    pWnd->SetWindowText("Hello World!");
    or CWnd* pWnd; pWnd->Attach(hMyHandle);

    MFC类中有的还提供了标准方法,比如Window 句柄:
    static CWnd* PASCAL FromHandle( HWND hWnd );
    HWND GetSafeHwnd( ) const;

    对于位图:
    static CBitmap* PASCAL FromHandle( HBITMAP hBitmap );
    static CGdiObject* PASCAL FromHandle( HGDIOBJ hObject );
    HGDIOBJ GetSafeHandle( ) const;

        有人说句并就是一个标示,一个ID号,是错误的。一个ID号可以包括多个资源,比如说单文档中的IDR_MAINFRAME,一般是指在硬盘上的资源。但是当把硬盘上的资源调入内存以后,将有一个句柄指向它,但是句柄只能指向一个资源。而且句柄知道所指的内存有多大。还有指针,指针指向地址,它不知道分配的内存有多大。
        但是如果你定义一个句柄,然后在VC里面右击鼠标,选择"go to definition of HANDLE,你会发现它的本质就是一个指针,但是它的作用不同于指针。

        句柄是个指针,指向一块内存,但至于这块内存跟句柄所标识的对象是怎么联系起来的,调用者不需要清楚,调用者只需要知道,这个句柄联系着一个win32对象。
        句柄是物理地址,可以跨进程传递,例如,HANDLE ha进程A的一个窗口,你可以在进程B中利用一个跟ha相等的值(相等就是说它们强制转成int32的值相等)初始化一个句柄,利用这个句柄你可以对进程 A的那个对象进行操作,例如MoveWindow,ShowWindow等。
        句柄包含了一些引用计数之类的东西,所以我的上一点说的给句柄赋值是不安全的,Windows API提供了一些函数,可以对句柄进行操作。

    句柄就是受限的指针
        它是由操作系统管理的,你不能通过它存取操作系统创建的数据结构

        操作系统在创建一个对象(如GDI, FILE)等的时候,它会为这个对象CONTEXT保留一块数据结构,然后把它放在一张全局表中。。句柄就是这块数据结构在表中的索引

        指针对应着一个数据在内存中的地址,得到了指针就可以自由地修改该数据。Windows并不希望一般程序修改其内部数据结构,因为这样太不安全。所以 Windows给每个使用GlobalAlloc等函数声明的内存区域指定一个句柄(本质上仍是一个指针,但不要直接操作它),平时你只是在调用API函数时利用这个句柄来说明要操作哪段内存。当你需要对某个内存进行直接操作时,可以使用GlobalLock锁住这段内存并获得指针来直接进行操作。
        lshgao的意见:
        句柄是指针的“指针”,使用句柄主要是为了利于windows在进程内存地址空间移动分配的内存块,以防止进程的内存空间被撕的四分五裂而存在过多的碎片。
        
        阿城的意见:
        句柄是一些表的索引也就是指向指针的指针。间接的引用对象,windows可以修改对象的"物理"地址和
        描述器的值,但是句柄的值是不变的。
        
        刘志用的意见:
        句柄和指针都是地址,不同在于:
        1,句柄所指的可以是一个很复杂的结构,并且很有可以是与系统有关的,比如说上面所说的线程的句柄,它指向的就是一个很类或者结构,他和系统有很密切的关系,当一个线程由于不可预料的原因,而终止时在系统就可以回它所占用的资料,如CPU,内存等等,反过来想可以知道,这个句柄中的某一些项,是与系统进行交互的。由于Windows系统,是一个多任务的系统,它随时都可能要分配内存,回收内存,重组内存。
        2,指针它也可以指向一个复杂的结构,但是通常是用户定义的,所以的必需的工作都要用户完成,特别是在删除的时候。
        但在VC++6.0中也有一些指针,它们都是处理一些小问题才用的,如最常见的字符的指针,它也是要用户处理的如果你动态分配了内存;但是Cstring 就不要用户处理了,它其实是VC++中的一个类,所以的操作都由成员函数完成,产生(分配)由构造函数,删除(回收)由析构函数完成。
        
        zjf问:
        你好,我在学习用vc++6.0编译多线程程序中遇到了很多句柄,但是不明白他的具体作用以及如何使用句柄,希望您能给我举几个具体实例,不甚感激!
        比如说: HANDLE hThread,它是怎样具体使用的?
        答:你使用CreateThead后函数会返回一个句柄,它代表这个线程。你可能会调用SetThreadPriority去修改线程的优先级,使用 ResumeThread去重新开始一个线程的运行,在调用这些函数时你都需要告诉系统你到底要操作哪个线程,而刚才返回的句柄派上用处了,这些函数的第一个参数就是线程的句柄。
        看VC中总是出现这个句柄的概念,以前一直以为就是指指针,但是越看越觉得不是这么简单,于是本着有问题百度一下的原则,看到如下解释,很是经典:

        csdn上有人说过:牧童遥指杏花村。
        牧童的手为指针,杏花村的牌子为句柄,杏花村酒店为对象的实例.

        句柄就是烤叉,用烤炉烤过鸭,鸡,牛,羊,狗么?
        炉子里的东西是看不见,摸不到的,但你能用叉子去控制,至于叉子上的是什么,你放进去前应该记住。呵呵

        句柄有时是指针,有时是索引,但他绝对是一把钥匙,内核句柄110的钥匙,GDI句柄是您的钥匙,只对您有效。

        单从概念上讲,句柄指一个对象的标识,而指针是一个对象的首地址。从实际处理的角度讲,即可以把句柄定义为指针,又可以把它定义为同类对象数组的索引,这两种处理方法都有优缺点,至于选用哪种方式,完全应该看实际需要,这可以说是一种程序设计上的技巧。那种单纯认为句柄是指针或索引的想法都是机械的、不确切的。其实,在Windows中类似的处理是很多的、很灵活的。再具个相似的例子:

        我们知道,在Windows中有个函数叫做CallWindowProc。
        故名思义,它的作用就是向指定的窗口过程传递一个消息。你也许会想,既然我已经有了窗口过程的指针,为什么我不可以直接通过这个指针调用该函数(这是C语言的内建功能)?事实上,在Win16中确实可以这么做,因为GetWindowLong返回的确实是该函数的指针。但在Win32 下,GetWindowLong返回的并不是该函数的指针,而是一个包含函数指针的数据结构的指针(MSDN上说返回的是一个窗口函数地址或它的句柄,就是指的这种情况)。该数据结构是可变的,但只要你使用CallWindowProc来调用的话是不会出错的。这里我们又看到使用句柄处理带来的好处。(补充说明一点:微软在这里之所以这么处理,是为了解决16位/32位以及ANSI/UNICODE的转化问题)

        看来,句柄很多时候是一个用于描述和标记一个资源的数据结构的指针,而不是资源本身的指针,句柄中可能包含资源的指针,但是根多时候不仅仅是这样。

    本文转自:http://xuejianxinokok.blog.163.com/blog/static/4043757720099301341319/

    http://blog.csdn.net/wangningyu/article/details/4943184

  • 相关阅读:
    HDU 2089 不要62
    HDU 5038 Grade(分级)
    FZU 2105 Digits Count(位数计算)
    FZU 2218 Simple String Problem(简单字符串问题)
    FZU 2221 RunningMan(跑男)
    FZU 2216 The Longest Straight(最长直道)
    FZU 2212 Super Mobile Charger(超级充电宝)
    FZU 2219 StarCraft(星际争霸)
    FZU 2213 Common Tangents(公切线)
    FZU 2215 Simple Polynomial Problem(简单多项式问题)
  • 原文地址:https://www.cnblogs.com/findumars/p/5928707.html
Copyright © 2011-2022 走看看