【问题标题】:Is it safe to "double-close" a handle using CloseHandle?使用 CloseHandle “双重关闭”句柄是否安全?
【发布时间】:2010-07-06 02:50:56
【问题描述】:

多次调用 CloseHandle 有什么影响?

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

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

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

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

这可能吗?

Windows 如何选择句柄 ID?

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

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

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

谢谢!

约翰

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

【问题讨论】:

  • 你指的是什么“共享句柄”?每个进程都应该创建关闭它自己的(相同的)管道句柄。句柄如何最终被共享?唉,答案“只是不要”,但那是因为句柄根本不应该被共享。

标签: winapi handles


【解决方案1】:

简单到可以检查:

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,句柄也可以用于任何类型的对象——也许是互斥体,也许是别的东西。两次执行 CloseHandle() 可能会产生令人惊讶的后果。
【解决方案2】:

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

【讨论】:

  • 嗯,也许我理解错了。但我确实看到了管道的客户端关闭管道的问题,然后服务器抛出“无效句柄”异常(在调试模式下)。
【解决方案3】:

可能会发生两件事:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-09
    • 2014-12-15
    • 1970-01-01
    • 2021-11-02
    • 1970-01-01
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    相关资源
    最近更新 更多