句柄泄露与CloseHandle()

摘自:http://blog.chinaunix.net/uid-21783276-id-2689047.html

CloseHandle()函数的使用??



很多程序在创建线程都这样写的:
............
ThreadHandle = CreateThread(NULL,0,.....);
CloseHandel(ThreadHandle );
。。。。。
这不是刚好创建又关闭了吗?线程怎么运行呢?

================================================

Closing a thread handle does not terminate the associated thread. To remove a thread object, you must terminate the thread, then close all handles to the thread.

================================================

1, 线程和线程句柄(Handle)不是一个东西,线程是在cpu上运行的.....(说不清楚了),线程句柄是一个内核对象。我们可以通过句柄来操作线程, 但是线程的生命周期和线程句柄的生命周期不一样的。线程的生命周期就是线程函数从开始执行到return,线程句柄的生命周期是从 CreateThread返回到你CloseHandle()。

2,所有的内核对象(包括线程Handle)都是系统资源,用了要还的,也就是说用完后一定要closehandle关闭之,如果不这么做,你系统的句柄资源很快就用光了。

3, 如果你CreateThread以后需要对这个线程做一些操作,比如改变优先级,被其他线程等待,强制TermateThread等,就要保存这个句柄, 使用完了在CloseHandle。如果你开了一个线程,而不需要对它进行如何干预,CreateThread后直接CloseHandle就行了。


所以
CloseHandel(ThreadHandle );
只是关闭了一个线程句柄对象,表示我不再使用该句柄,即不对这个句柄对应的线程做任何干预了。并没有结束线程。

如果你觉得多了一个变量,也可以写为:
CloseHandel(CreateThread(NULL,0,.....));

================================================================

《windows核心编程》上说调用closehandle(HANDLE)表示创建者放弃对该内核对象的操作。如果该对象的引用对象记数为0就撤消该对象。


====================================================================

在 线程创建后马上调用CloseHandle()是个良好的做法,这里不会影响线程的执行,就是因为即使你close了这个handle,它的内部记数也不 为零.    但如果你不关,在线程结束后,那个线程对象将滞留于内存中,也就是说你有handle    leak.  
   
   返回这个handle给你,是让你有机会对这个线程实施外部动作,诸如waitforsingleobject之类.  

==================================================================

CloseHandle的功能是关闭一个打开的对象句柄,该对象句柄可以是线程句柄,也可以是进程、信号量等其他内核对象的句柄,而ExitThread的功能是终止一个线程,它所接受的参数是一个线程的退出码。  
   
   通过调用CloseHandle可以告知系统,已经完成了对某一内核对象的操作,该函数首先检查调用进程的句柄表,来确认进程是否对该句柄所指向的对象有 访问权,如果句柄无效则返回FALSE,如果有效,系统将得到该内核对象的数据结构的地址,把结构中的使用计数成员减1,如果计数变为0,则将从内核中释 放该内核对象。  
   
   如果计数还未到0,就意味着还有其他的进程在使用这个内核对象,那么它就不会被释放。  
   
   ExitThread是推荐使用的结束一个线程的方法,当调用该函数时,当前线程的栈被释放,然后线程终止,相对于TerminateThread函数来说,这样做能够更好地完成附加在该线程上的DLL的清除工作。  
   
   如果需要进一步的信息,您可以参看:  
   http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/handobj_289x.asp   http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/prothred_531g.asp   
   等有关的MSDN信息。

==================================================================

线程作为一种资源创建后不只被创建线程引用,我想系统自身为了管理线程也会有一个引用,所以用户线程释放线程句柄后,引用计数也不会是零。引用计数是资源自我管理的一种机制,资源本身以引用计数为零来得知别人不再需要自己,从而把自己kill掉。

=================================================================

CreateThread后那个线程的引用计数不是1,调用CloseHandle只是说自己对这个线程没有兴趣了,线程还是正常运行的

=================================================================

CreateThread后那个线程的引用计数不是1,而是2。  
   
   creating    a    new    process    causes    the    system    to    create    a    process    kernel    object    
   and    a    thread    kernel    object.    At    creation    time,    the    system    gives    each    object    
   an    initial    usage    count    of    1.    Then,    just    before    CreateProcess    returns,    the    
   function    opens    the    process    object    and    the    thread    object    and    places    the    
   process-relative    handles    for    each    in    the    hProcess    and    hThread    members    of    
   the    PROCESS_INFORMATION    structure.    When    CreateProcess    opens    these    objects    
   internally,    the    usage    count    for    each    becomes    2.

=================================================================

创建新的进程后,记数初始化为1,而函数需要返回进程内核对象的句柄,相当于打开一次新创建的类核对象,记数再加1

------------------------------------

CloseHandle函数

     BOOL CloseHandle(

     HANDLE hObject

     );

     参数

     hObject :代表一个已打开对象handle。

     返回值

     TRUE:执行成功;

     FALSE:执行失败,可以调用GetLastError()获知失败原因。

     函数说明:

     关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。

     若在线程执行完之后,没有调用CloseHandle,在进程执行期间,将会造成内核对象的泄露,相当于句柄泄露,但不同于内存泄露,这势必会对系统的效率带来一定程度上的负面影响。但当进程结束退出后,系统会自动清理这些资源。


本文来自CSDN博客,转载请标明出处: http://blog.csdn.net/lhsxsh/archive/2009/02/18/3905505.aspx

"句柄" 类似指针, 但通过指针可读写对象, 通过句柄只是使用对象;
有句柄的对象一般都是系统级别的对象(或叫内核对象); 之所以给我们的是句柄而不是指针, 目的只有一个: "安全";
貌似通过句柄能做很多事情, 但一般把句柄提交到某个函数(一般是系统函数)后, 我们也就到此为止很难了解更多了; 事实上是系统并不相信我们.

不管是指针还是句柄, 都不过是内存中的一小块数据(一般用结构描述), 微软并没有公开句柄的结构细节, 猜一下它应该包括: 真实的指针地址、访问权限设置、引用计数等等.

CloseHandle((HANDLE) hThreadHandle); 
不是关掉线程,只是让该句柄失效,不能通过该句柄继续控制该线程而已

本文转自 http://tieba.baidu.com/f?kz=785454910



 另外:

线程创建后,立刻调用CloseHandle的原因

 

HANDLE threadhandle = CreateThread(NULL, 0, RecvThreadProc, NULL, NULL, NULL); 

CloseHandle(threadhandle); 

不明白为什么创建线程后,要马上把线程的句柄关闭,这样做的目的是什么? 这样做会杀掉线程吗?

解答:

     创建线程后返回了线程句柄,新创建的线程内核对象的使用计数是2,一个是线程本身,一个是创建线程的线程,创建线程的线程closehandle后,新的线程的内核对象使用计数为1,当这个新线程结束运行后内核对象的使用计数还要减1,这时内核对象的使用计数是0,则系统会自动删除新线程的内核对象,这是正常的处理流程。


     你如果不显示的调用closehandle,则新线程结束运行后,由于内核对象使用计数为1,所以不会删除内核对象,会造成内存泄露,不过当整个进程结束时操作系统会自动关闭该进程的所有的内核对象包括这个新线程的内核对象,所以你不调用closehandle问题不大,只是在你的进程运行的时候会造成内存泄露,进程结束后系统是会自动清理的。

 

如果你创建线程后连续两次调用CloseHandle会怎样呢?系统会立即删除新线程的内核对象,线程会立即终止么?不会的,为什么?我也没弄清楚.................

 


你可能感兴趣的:(windows核心编程)