6

多次调用 CloseHandle 意味着什么?

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

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

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

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

这可能吗?

Windows 如何选择句柄 ID?

是否可以保证句柄值的重用频率?

(例如,TCP 确保端口号不能在某个时间范围内重复使用)。

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

谢谢!

约翰

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

4

3 回答 3

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 或其任何组合重复此实验。

于 2010-07-05T11:22:07.510 回答
4

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

于 2010-07-05T12:00:06.073 回答
1

有两种情况可能发生:

  1. 您关闭由其他代码打开的句柄。这可能不会影响您的代码,但对于其他代码来说可能是灾难性的。
  2. 如果您在附加调试器的情况下运行,则会导致应用程序崩溃,因为操作系统在检测到无效句柄被关闭时会引发异常。

恕我直言,这些都不是特别有吸引力。

于 2010-07-05T18:50:56.820 回答