能力值:
( LV2,RANK:10 )
|
-
-
2 楼
首先告诉你的是,书上讲的是对的。
如果CloseHandle关闭了进程或者主线程句柄, 系统开新进程的id可能会使用原来的那个,
这也就是说,如果closeHandle了进程或主线程句柄,并且该进程或线程已经退出,那么,他们对应的id也就不再有效,这是如果有新的进程或线程产生,那么使用的id就很有可能是这个id。
比如,某个进程的id是4321,当这个进程退出,并且父进程closehandle了子进程句柄,那么这是的4321就不再有任何意义。此时如果有第二个进程产生,那么这个进程id可是4322,也可能是4321.
你所说的资源管理器运行2个相同名字的进程,因为进程都再运行,因此它的id是有效而且是唯一的。只要当其中一个进程不再运行,并且调用它的父进程也closehandle了,那么它的id才被收回,也即此id不再有效。
总之,这个进程或线程id有效,需要2个条件:1.进程或线程仍然在运行。2.产生该进程或线程的父亲必须closehandle。此时进程或线程对象才真正从内核中销毁。对象销毁了,那么代码对象的唯一id也就随之不再有效。
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
谢谢.
你说的怎么变成2个条件了(和书上矛盾了)
引用的第2段文字明明是只有一个条件,只要关闭了句柄, id就无效了,内核对象引用就减1了(当然内核对象本身不一定销毁)
还有
我写代码做过试验的
CreateProcess(.....,&pi); 打开一个notepad.exe (没有手动按窗口X关闭)
然后立刻关闭句柄
ret1 = CloseHandle(pi.ThreadHandle);
ret2 = CloseHandle(pi.ProcessHandle);
ret1 ret2都是TRUE,也就是句柄成功销毁
如果按照你说的, 其实id没有失效(因为notepad.exe窗口没关闭), 绝对不会被重用。-- 这样的话,我也就没有疑问了 -- 资源管理里不会出现2个相同id的进程
如果按照书上说的, id就已经失效了,可以被重用 -- 这样的话, 就可能出现2个相同的id哦 ???
另外,
我还发现一个问题, 连续调用个关闭句柄2次,第2次的时候会引发crt异常,真奇怪
也就是这样写
ret1 = CloseHandle(pi.ThreadHandle);
ret2 = CloseHandle(pi.ProcessHandle);
ret1 = CloseHandle(pi.ThreadHandle); //<--crt异常,调试弹出非法框
ret2 = CloseHandle(pi.ProcessHandle); //<--crt异常,调试弹出非法框
按照以往的实际代码经验,句柄参数不管是NULL,还是乱七八遭的数据,只要内核找不到这个数值(即认为非法句炳), 则CloseHandle返回FALSE, 并不会异常的。
朋友们能解释下为什么会出现crt异常么, 谢谢了
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
1.我说的并与书上讲的并不矛盾。进程id有没有失效,其实就看内核对象还是否存在。如果存在,其id就有效,否则其id就没有意义。那么内核对象有没有销毁,内核对象引用有没有减到0。CreateProcess,内核对象引用增加了两次。closehandle减了一次,进程退出又减了1次。故此时做了销毁,id也不复存在。
2.closehandle无效句柄,将可能会引起异常。我个人的做法是:CloseHandle后,置句柄值为NULL。就像指针一样处理的,如:
CloseHanle(hDevice);
hDevice = NULL;
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
补充一下:
关闭句柄后,置空的另一个好处,是避免关闭另一个并不希望关闭的句柄值。
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
|
|
|