博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
句柄泄露与CloseHandle()
阅读量:4029 次
发布时间:2019-05-24

本文共 2990 字,大约阅读时间需要 9 分钟。

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的清除工作。 

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

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

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

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

CreateThread后那个线程的引用计数不是1,而是2。

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

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

CloseHandle函数

     BOOL CloseHandle(

     HANDLE hObject

     );

     参数

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

     返回值

     TRUE:执行成功;

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

     函数说明:

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

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


本文来自CSDN博客,转载请标明出处:

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

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

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

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

你可能感兴趣的文章
玩转Java高并发?请先说明下并发下的惊群效应
查看>>
轻松搭建Redis 5.0集群环境,只需十分钟
查看>>
Jmeter压测错误,Address already in use: connect
查看>>
高并发API网关,Spring Cloud Gateway 之限流操作
查看>>
OAuth2.0 微服务认证授权,四种常见的授权模式
查看>>
Java 2019 面试宝典
查看>>
Redis面试题之持久化和五种部署方式
查看>>
搞定Spring Cloud断路器组件 Hystrix 的舱壁模式
查看>>
mybatis之大于、小于、大于等于和小于等于的写法
查看>>
如何实现 Oracle 的自增序列,两步轻松搞定
查看>>
不要等到Oracle磁盘空间满了,再去查表空间使用情况
查看>>
Hive SQL常用命令总结,大数据开发人员按需收藏
查看>>
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/io/IOUtils
查看>>
使用 Springboot 对 Kettle 进行调度开发
查看>>
Kettle链接MySQL报错:Driver class 'org.gjt.mm.mysql.Driver' could not be found
查看>>
Python的Turtle库非常实用,绘制图形竟然这么简单
查看>>
JVM面试要点:G1 垃圾收集器和如何做到可预测的停顿
查看>>
阿里巴巴倡导的数据中台,到底是什么东东
查看>>
揭底JVM,怎么能不了解G1垃圾收集器
查看>>
如何优雅的编程,lombok你怎么这么好用
查看>>