关闭WinAPI HANDLE的正确方法(避免重复关闭)

2023-11-24

我有一些句柄,我需要关闭它。代码中的某些地方可能会关闭句柄。那么,这是关闭句柄的正确方法吗?

HANDLE h;
....
if ( h != INVALID_HANDLE_VALUE ) {
  ::CloseHandle(h);
  h = INVALID_HANDLE_VALUE;
}

关于位图句柄还有同样的问题:

HBITMAP hb;
....
if ( hb != INVALID_HANDLE_VALUE ) {
  ::DeleteObject(hb);
  hb = INVALID_HANDLE_VALUE;
}

EDIT:


并非所有函数都使用HANDLE use CloseHandle(),有些使用其他关闭函数代替。另外,并非所有HANDLE价值观的运用INVALID_HANDLE_VALUE, 任何一个。一些使用NULL反而。

HBITMAP从不使用INVALID_HANDLE_VALUE,它总是使用NULL。你永远不应该打电话DeleteObject() for an HBITMAP你不拥有。

所以简短的答案是 - 如果您正在尝试创建一些通用句柄管理,请不要打扰。你很可能会弄错。如果您分配/打开某个句柄,您必须知道关闭它的正确方法,您无法猜测它。

如果您希望手柄能够自行管理,那么 RAII 是最佳选择。我更喜欢使用具有专门特征的模板类来减少不同类型句柄的代码重复,例如:

template< class traits >
class HandleWrapper
{
private:
    traits::HandleType FHandle;

public:
    HandleWrapper()
        FHandle(traits::InvalidValue)
    {
    }

    HandleWrapper(const traits::HandleType value)
        FHandle(value)
    {
    }

    ~HandleWrapper()
    {
        Close();
    }

    void Close()
    {
        if (FHandle != traits::InvalidValue)
        {
            traits::Close(FHandle);
            FHandle = traits::InvalidValue;
        }
    }

    bool operator !() const {
        return (FHandle == traits:::InvalidValue);
    }

    operator bool() const {
        return (FHandle != traits:::InvalidValue);
    }

    operator traits::HandleType() {
        return FHandle;
    }
};

.

struct KernelHandleTraits
{
    typedef HANDLE HandleType;
    static const HANDLE InvalidValue = INVALID_HANDLE_VALUE;

    static void Close(HANDLE value)
    {
        CloseHandle(value);
    }
};

HandleWrapper<KernelHandleTraits> hFile(CreateFile(...));

.

struct NullKernelHandleTraits
{
    typedef HANDLE HandleType;
    static const HANDLE InvalidValue = NULL;

    static void Close(HANDLE value)
    {
        CloseHandle(value);
    }
};

HandleWrapper<NullKernelHandleTraits> hMapping(CreateFileMapping(...));

.

struct FileMapViewTraits
{    
    typedef void* HandleType;
    static const void* InvalidValue = NULL;

    static void Close(void *value)
    {
        UnmapViewOfFile(value);
    }
};

HandleWrapper<FileMapViewTraits> hView(MapViewOfFile(...));

.

struct GDIBitmapHandleTraits
{    
    typedef HBITMAP HandleType;
    static const HBITMAP InvalidValue = NULL;

    static void Close(HBITMAP value)
    {
        DeleteObject(value);
    }
};

HandleWrapper<GDIBitmapTraits> hBmp(CreateBitmap(...));

Etc.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关闭WinAPI HANDLE的正确方法(避免重复关闭) 的相关文章

随机推荐

  • 从网络中的另一台机器 Ping Docker 容器

    我创建了一个 docker 容器 并尝试在容器的 bash 中 ping www google com 并且它有效 我还尝试从主机 ping 容器 它工作得很好 但是 当我尝试从网络中的外部系统 ping 容器时 它给了我一个请求超时异常
  • CakePHP 从数据库中查询最近的纬度经度

    在 CakePHP v3 应用程序中 如何根据传递的 lat lng 值检索最接近的结果 我想让它们恢复为原生 CakePHP 实体 所以像这样 public function closest lat lng sightings recor
  • 我应该将时区与 Postgres 和 JDBC 的时间戳分开存储吗?

    看起来 也许我是错的 如果你想保留 JDBC 和 Postgres 发生问题时的时区 你需要将时区与时间戳分开存储 也就是说我更愿意给我的 ORM JDBC JPA 一个 JavaCalendar 或乔达DataTime 与说时区Ameri
  • 动态创建的文本框的 JavaScript 验证

    在表单中 通过单击 添加 按钮动态创建文本框 以便在新行中创建文本框 现在我的问题是动态创建的文本框的验证 以便如果有任何文本框 它会显示一条消息单击 提交 按钮提交表单时留空 请帮助我 EDIT
  • Python Plotly - 对齐散点图和条形图的 Y 轴

    我正在尝试使用散点图和图形元素创建一个绘图图 一切都很顺利 但有一个问题 两个 Y 轴没有围绕 0 对齐 我尝试过使用不同的属性 例如 mirror 和tick0 我也尝试遵循plotly网站上的示例 但它主要是具有相同图形类型的多个y轴
  • 在数据重新加载时保存 WPF TreeView 状态

    我正在使用 TreeView 在 UI 中显示我的数据 现在 我的应用程序每 5 秒刷新一次 以便显示最新的数据 有没有办法即使在窗口重新加载后也可以保存树视图的展开状态或折叠状态 因为如果我有大量数据并且需要超过 5 秒才能转到所需数据
  • 如何在 Blazor 组件上进行双向绑定

    我想创建自定义输入 所以我创建了这个组件 MyInputComponent razor div div
  • jquery历史记录插件

    我正在使用这个插件 http plugins jquery com project history 在本页面 http www crtaci info index php autocom majice 我不知道为什么 但似乎我不知道该怎么做
  • 如何关闭额外的日志记录?

    我有一个使用 Spring 和 CXF 的 Java 服务 该代码来自以前的开发人员 我正在提供维护 但我在日志中看到了这一点 Apr 16 2013 1 44 11 PM org apache cxf interceptor Abstra
  • 如何让 Winston 使用 Webpack?

    我有一个使用 Node js 的电子应用程序 我想使用 Winston 登录应用程序 我已将winston 添加到我的package json 文件中 但是当我运行webpack 的构建命令时 我收到了winston 中colors js
  • 使用 ctypes 模块从 python 调用的共享库捕获打印输出

    我正在使用一个通过 ctypes 模块调用的共享库 我想将与此模块关联的标准输出重定向到我可以在程序中访问的变量或文件 然而 ctypes 使用与 sys stdout 不同的标准输出 我将演示我在使用 libc 时遇到的问题 如果有人复制
  • 如何检查日期时间是否在中午之前

    我在 python 中有一个日期时间对象 我想创建一个函数来检查输入是在日期时间当天的上午还是下午 即中午 12 点之前或之后 如何手动创建时间12 00我可以为此使用大于或小于符号吗 lt gt 致电datetime datetime t
  • 在 SQL Server 中迭代 XML 变量

    我在存储过程 SQL Server 2008 中有一个 XML 变量 其示例值为
  • Android 4.0 (API 14+) 中 Activity 之间的默认转换是什么

    我构建了一个包含相当多活动的应用程序 我希望在它们之间实现 进入时从右滑动 退出时从左滑动 转换 我不止一次地读到幻灯片过渡应该是 Android 默认设置 但在我正在开发的设备上 过渡默认是淡入 淡出 Galaxy Tab 2 7 在 I
  • 对 OpenSSL 非阻塞 I/O 感到困惑

    一般来说 OpenSSL 库 C API 似乎提供了两种方法来做所有事情 您可以使用根据您的喜好配置的普通系统套接字 或者您可以使用 OpenSSLBIO有点像流的对象 然而 我经常对一些重复的功能感到困惑 例如 如何使 SSL 连接非阻塞
  • WCF .NET Core - WsHttpBinding 配置project.json

    如何使用 NET core配置wsHttpBinding 我应该在Project json文件中配置吗 在 NET Core之前的配置如下
  • Fortran 中的特定双精度函数有用吗?

    我注意到使用 gfortrantan函数返回与其参数相同类型的实值 例如一个人可以通过real kind 4 real kind 8 or real kind 16 并得到结果real kind 4 real kind 8 or real
  • 在 C 语言中编译时评估的预处理器函数

    我想编写在以下位置评估的预处理器函数 数组 编译时间 例如 如果我定义 define MYARR 5 4 3 2 1 0 然后 代码 int x R 0 应表示为 int x 5 给编译器 当然索引中只能使用文字 如果代码大小 内存很关键并
  • 如何控制 Ember.js 在何处附加渲染的应用程序模板?

    我正在尝试将我的 Ember 应用程序切换为使用 Ember Router 但在附加应用程序模板的位置上遇到问题 当我调用 App initialize 时 它会在文档末尾呈现模板 有没有办法指定渲染的应用程序模板附加到的位置 我的应用程序
  • 关闭WinAPI HANDLE的正确方法(避免重复关闭)

    我有一些句柄 我需要关闭它 代码中的某些地方可能会关闭句柄 那么 这是关闭句柄的正确方法吗 HANDLE h if h INVALID HANDLE VALUE CloseHandle h h INVALID HANDLE VALUE 关于