C++ 如何确保并强制拥有句柄以防止不必要的CloseHandle调用? TL;博士

C++ 如何确保并强制拥有句柄以防止不必要的CloseHandle调用? TL;博士,c++,winapi,c++14,handle,C++,Winapi,C++14,Handle,假设我实现了一个类,该类实现了一个返回句柄的API。 假设我的类是句柄的所有者,负责创建、更新和关闭句柄 如何防止API的调用方关闭我的句柄并破坏我的设计 背景 CreateToolhelp32Snapshot是一个昂贵的调用,必须智能地使用。 我的解决方案中有许多项目,每个项目都不小心调用了CreateToolhelp32Snapshot 我想实现一个包装类,它提供对CreateToolhelp32Snapshot的“智能”访问 我的类将是CreateToolhelp32Snapshot返回的

假设我实现了一个类,该类实现了一个返回
句柄的API。
假设我的类是
句柄的所有者,负责创建、更新和关闭句柄

如何防止API的调用方关闭我的句柄并破坏我的设计

背景
CreateToolhelp32Snapshot
是一个昂贵的调用,必须智能地使用。 我的解决方案中有许多项目,每个项目都不小心调用了
CreateToolhelp32Snapshot

我想实现一个包装类,它提供对
CreateToolhelp32Snapshot
的“智能”访问

我的类将是
CreateToolhelp32Snapshot
返回的
HADNLE
的所有者,并将在需要时更新它(重新调用
CreateToolhelp32Snapshot

为了简单起见,让我们假设我的应用程序是一个进程&线程,并且我的类只有一个实例

假设我实现了一个类,该类实现了一个返回句柄的API

你还了把手,破坏了你的设计。包装器的用户不应该关心句柄,而应该关心他们想要的数据,就像您案例中的模块列表一样。公开可以将此类数据返回给用户的API

class snapshot
{
    public:
    snapshot()
    {
        m_handle = CreateToolhelp32Snapshot(...);
    }
    ~snapshot()
    {
        CloseHandle(m_handle);
    }
    getModules()
    {
        // use m_handle to return a list of modules.
    }
    private:
    HANDLE m_handle;
};
假设我实现了一个类,该类实现了一个返回句柄的API

你还了把手,破坏了你的设计。包装器的用户不应该关心句柄,而应该关心他们想要的数据,就像您案例中的模块列表一样。公开可以将此类数据返回给用户的API

class snapshot
{
    public:
    snapshot()
    {
        m_handle = CreateToolhelp32Snapshot(...);
    }
    ~snapshot()
    {
        CloseHandle(m_handle);
    }
    getModules()
    {
        // use m_handle to return a list of modules.
    }
    private:
    HANDLE m_handle;
};

你不能。只要您不愿意完全封装
句柄的所有用途
,可以直接访问
句柄
的外部代码就可以将其关闭。这与能够执行
delete smart_ptr.get()没有区别


C++可以保护您免受意外误用。它不能保护你免于背信弃义。如果使用smart handle类的用户没有收到smart handle类是
句柄的所有者的备忘录,您就无能为力了。

您做不到。只要您不愿意完全封装
句柄的所有用途
,可以直接访问
句柄
的外部代码就可以将其关闭。这与能够执行
delete smart_ptr.get()没有区别


C++可以保护您免受意外误用。它不能保护你免于背信弃义。如果使用smart handle类的用户没有收到smart handle类是
句柄的所有者的备忘录,您就无能为力了。

您可以做的是使用DuplicateHandle并要求调用方调用CloseHandle。除此之外,您必须信任调用者。

您可以使用DuplicateHandle并要求调用者调用CloseHandle。除此之外,您必须信任调用方。

如果我要实现该类,我只需编写方法
Enumerate
,并调用另一组函数
CreateToolhelp32Snapshot
,然后调用
CloseHandle
句柄
不是类本身的一部分,而是
枚举
方法的局部句柄。 枚举将填充所需的结构(用户定义),并将创建该结构的
向量
(或者(
无序
映射
,如果需要一些PID->ProcessInformation访问)。 该类将促进方法获取枚举数据。对于一个一流的C++类,我实际上会实现<代码>开始<代码>和<代码>结束>代码>方法,以便类/对象可以使用基于范围的<代码> < <代码>循环> < /p>
为什么在实际处理
CreateToolhelp32Snapshot
时确实需要延迟?当真正的调用方在该句柄上调用一些安全的Win32 API时,正在运行的进程的状态就会发生变化。如果类的对象停留很长时间(er),那么您所拥有的就是针对该句柄的陈旧/不一致的信息

如果要实现该类,我只需编写方法
Enumerate
,并调用另一组函数
CreateToolhelp32Snapshot
,然后调用
CloseHandle
句柄
不是类本身的一部分,而是
枚举
方法的局部句柄。 枚举将填充所需的结构(用户定义),并将创建该结构的
向量
(或者(
无序
映射
,如果需要一些PID->ProcessInformation访问)。 该类将促进方法获取枚举数据。对于一个一流的C++类,我实际上会实现<代码>开始<代码>和<代码>结束>代码>方法,以便类/对象可以使用基于范围的<代码> < <代码>循环> < /p>
为什么在实际处理
CreateToolhelp32Snapshot
时确实需要延迟?当真正的调用方在该句柄上调用一些安全的Win32 API时,正在运行的进程的状态就会发生变化。如果类的对象停留很长时间(er),那么您所拥有的就是针对该句柄的陈旧/不一致的信息

如果
句柄
属于您的类实现,就不要将其分发给客户机。如果您需要为客户端提供与类通信的方式,请为他们提供您制作的句柄类型,这样您的类就可以映射到实际的
句柄
,而不会离开您的类。如果您以正常方式隐藏句柄的实现(例如pimpl),您应该不会遇到很多问题。句柄不创建或删除任何内容,您只需调用两个API来创建和销毁。但是我发现我没有得到任何东西。@I我包装类的可检测客户端需要
句柄
才能使用许多其他WinAPI。我不想封装使用该句柄的整个API系列