我有一些把手,我需要关闭它。 有一个在代码,其中手柄可关闭一些地方。 所以,这是关闭手柄正确的方式?
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;
}
编辑:我认为,有一些误解。 我知道CloseHandle
是关闭句柄。 我想知道关闭句柄有道。 类似的情况出现与删除指针。
Foo *foo = new Foo();
// for example there is 2 functions that can delete foo
void bar() {
....
delete foo;
}
void duck() {
....
delete foo;
}
所以,下面的代码意味着问题:
bar();
duck();
有一些变通方法对于这种情况。 我们需要定义bar
和duck
这样的功能:
void bar() {
....
if (foo) {
delete foo;
foo = NULL;
}
}
void duck() {
....
if (foo) {
delete foo;
foo = NULL;
}
}
因此,我们避免重复的foo删除。 现在的问题是什么是关闭句柄的正确方法? 我的意思是,如何避免重复收盘处理问题?
这并不是说使用所有功能HANDLE
使用CloseHandle()
一些使用其他功能收盘代替。 此外,并非所有HANDLE
值使用INVALID_HANDLE_VALUE
,无论是。 一些使用NULL
来代替。
HBITMAP
从不使用INVALID_HANDLE_VALUE
,它总是使用NULL
。 你应该调用DeleteObject()
为HBITMAP
你没有自己。
所以,简单的答案是 - 如果你想创造一些通用手柄的管理,不要打扰。 你可能弄错了。 如果分配/打开一些把手,你必须知道正确的方法来关闭它,你不能在其猜测。
如果你想把手来管理自己,那么RAII是最好的选择。 我更喜欢使用专门性状的模板类,以减少differrent类型的手柄,如重复的代码:
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(...));
等等。
使用RAII模式 。
包装一个手柄成分配在构造函数中的手柄并破坏它的析构函数的类。 你可以找到在MFC中一些例子,如CGdiObject类像GDI对象HBITMAP
。
另见本SO问题: RAII和智能指针在C ++
是。
-
CloseHandle()
关闭windows 内核对象句柄。 -
DeleteObject()
删除GDI对象。
我觉得你的困惑来自于他们两个被称为“手柄”,但它们是不同的对象的“类”。 在术语手柄HBITMAP
用在这里更是“不透明标识符”。 此外,还有大量其假设的“把手” ==“Windows内核句柄”文档。
一般来说,如果你想知道如何删除的东西,你应该看看构造函数的文档。
下面的代码也许是你追求的:
BOOL CloseValidHandle(HANDLE& handle)
{
if (handle != INVALID_HANDLE_VALUE && handle != 0)
{
if (CloseHandle(handle))
{
handle = INVALID_HANDLE_VALUE;
return TRUE;
}
else
{
return FALSE;
}
}
return TRUE;
}
这是没有RAII但它可以帮助删除/关闭处理器。
class HandleDel : boost::notcopyable{
public:
HandleDel(HANDLE h, HANDLE invalid, BOOL(WINAPI *del)(HANDLE)):
h(h), invalid(invalid), del(del){
}
~HandleDel(){
if ( h != invalid ) del(h);
}
private:
HANDLE h;
HANDLE invalid;
BOOL(WINAPI *del)(HANDLE);
};