使用CloseHandle“双关闭”句柄是否安全?

时间:2010-07-05 11:03:06

标签: winapi handles

多次调用CloseHandle会有什么影响?

文档说“你不应该”,但我认为我有一个现实的案例,其命名管道可能会在外部关闭句柄(见帖子末尾)。

在这种情况下,CloseHandle在调试模式下抛出异常,这表明开发人员认为这很严重,但文档并不完全清楚。

(礼貌请求:请避免回答“只是不要!”:-)。当然应该避免不止一次关闭一个手牌,当然还有很好的技巧来帮助解决这个问题:如果你不这样做,我只会感兴趣。

我听说有人建议如果操作系统很快重复使用句柄,你最终可能会关闭另一个不同的句柄。

这可能吗?

Windows如何选择句柄ID?

是否有关于如何定期重复使用句柄值的保证?

(例如,TCP确保端口号不能在特定时间范围内重用)。

你可以关闭句柄类型的句柄吗?例如,我是否可以认为我正在关闭管道但最终关闭了一个事件?

谢谢!

约翰

(上下文:我在客户端/服务器模型中使用命名管道。在我看来很难确保确保一方确保关闭句柄,例如在进程崩溃/被杀案例中。也许我我错了,但我觉得MSDN示例代码似乎允许客户端关闭共享句柄,然后当服务器尝试关闭它时,它已经关闭了。

3 个答案:

答案 0 :(得分:12)

足够简单,可以检查:

HANDLE h = 0;
h = CreateMutex(NULL, TRUE, NULL);
printf("%X\n", h);
CloseHandle(h);
h = 0;
h = CreateMutex(NULL, TRUE, NULL);
printf("%X\n", h);

在我的WinXP x64中,这产生了:

2E8
2E8

所以你有它。
与TCP端口不同,句柄会立即回收。

使用您喜欢的API或其任何组合重复此实验。

答案 1 :(得分:4)

你可能有错误的管道心理图像。它有两个末端,每个末端由不同的句柄表示。是的,必须调用CloseHandle两次才能使管道实例消失。但由于它们是不同的句柄,因此永远不会引起任何问题。另请注意,句柄实例是特定于进程的。即使它们在两个进程中具有相同的值,它们也不会引用相同的管道端点。

答案 2 :(得分:1)

可能会发生两件事:

  1. 您关闭其他代码打开的句柄。这可能不会影响您的代码,但对其他代码来说可能是灾难性的。
  2. 如果您使用附加的调试器运行,则会导致应用程序崩溃,因为操作系统会在检测到无效句柄被关闭时引发异常。
  3. 这些都不是特别有吸引力恕我直言。