使用带有自定义删除程序的shared_ptr来实现HANDLE RAII兼容 [英] Making a HANDLE RAII-compliant using shared_ptr with a custom deleter

查看:227
本文介绍了使用带有自定义删除程序的shared_ptr来实现HANDLE RAII兼容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近在 SO 。
但是,我的HANDLE示例仍然有一些实现问题。

I've recently posted a general question about RAII at SO. However, I still have some implementation issues with my HANDLE example.

A HANDLE windows.h 中的 void * 。因此,正确的 shared_ptr 定义需要

A HANDLE is typedeffed to void * in windows.h. Therefore, the correct shared_ptr definition needs to be

std::tr1::shared_ptr<void> myHandle (INVALID_HANDLE_VALUE, CloseHandle);

示例1 CreateToolhelp32Snapshot :返回 HANDLE 并起作用。

const std::tr1::shared_ptr<void> h
    (CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL), CloseHandle);

由于在定义中使用 void 什么是正确的方法?)问题继续,当我尝试调用一些更多的winapi命令与这个指针。

As I use void in the definition (what is the correct way?) problems go on, when I try to call some more winapi commands with this pointer. They functionally work, but are ugly and I am sure that there has to be a better solution.

在下面的例子中, h 是通过顶部定义创建的指针。

In the following examples, h is a pointer which was created via the definition at the top.

示例2 OpenProcessToken :最后一个参数是 PHANDLE

OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
    (PHANDLE)&h);

示例3 Process32First :第一个参数是 HANDLE 。真的很丑陋。

Example 3 Process32First: first argument is a HANDLE. REALLY ugly.

Process32First(*((PHANDLE)&h), &pEntry);

示例4 与常量的简单比较 HANDLE 。真的很丑陋。

Example 4 simple comparison with a constant HANDLE. REALLY ugly.

if (*((PHANDLE)&h) == INVALID_HANDLE) { /* do something */ }

为HANDLE创建正确的shared_ptr的正确方法是什么?

What is the correct way to create a proper shared_ptr for a HANDLE?

推荐答案

示例1是OK

示例2是错误的。通过盲目投射到PHANDLE,shared_ptr逻辑被绕过。应该是这样的:

Example 2 is wrong. By blindly casting to PHANDLE, the shared_ptr logic is bypassed. It should be something like this instead:

HANDLE h;
OpenProcessToken(...., &h);
shared_ptr<void> safe_h(h, &::CloseHandle);

或者,要分配给预先显示的shared_ptr:

or, to assign to a pre-exising shared_ptr:

shared_ptr<void> safe_h = ....
{
  HANDLE h;
  OpenProcessToken(...., &h);
  safe_h.reset(h, &::CloseHandle);
}//For extra safety, limit visibility of the naked handle

自己的,安全的OpenProcessToken版本,返回一个共享句柄而不是采取一个PHANDLE:

or, create your own, safe, version of OpenProcessToken that returns a shared handle instead of taking a PHANDLE:

// Using SharedHandle defined at the end of this post
SharedHandle OpenProcess(....)
{
    HANDLE h = INVALID_HANDLE_VALUE;
    ::OpenProcessToken(...., &h);
    return SharedHandle(h);
}

示例3:无需采取这些弯路。这应该是确定:

Example 3: No need to take these detours. This should be ok:

Process32First(h.get(), ...);

示例4:同样,没有绕道:

Example 4: Again, no detour:

if (h.get() == INVALID_HANDLE){...}


b $ b

为了使事情更好,你可以typedef如下:

To make things nicer, you could typedef something like:

typedef shared_ptr<void> SharedHandle;

或更好的是,如果所有句柄都要用CloseHandle a shared_ptr并自动提供正确的删除程序:

or better yet, if all handles are to be closed with CloseHandle(), create a SharedHandle class wrapping a shared_ptr and automatically providing the right deleter:

// Warning: Not tested. For illustration purposes only
class SharedHandle
{
public:
  explicit SharedHandle(HANDLE h) : m_Handle(h, &::CloseHandle){};
  HANDLE get()const{return m_Handle.get();}

  //Expose other shared_ptr-like methods as needed
  //...

private:
  shared_ptr<void> m_Handle;
};

这篇关于使用带有自定义删除程序的shared_ptr来实现HANDLE RAII兼容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆