If your question is "is there already a SafeHandle
subclass that calls LocalFree
to free its handle", then yes, there is -- it's SafeLocalAllocHandle
. The class is internal
, so it's not available to the general public, but the code is obvious if you wanted to recreate it. If your question is "should I use such a class", well, that's a bit of a judgment call. CA2006
and the SafeHandle
documentation explain the design rationale: SafeHandle
avoids issues with handle recycling in multithreaded scenarios and has special support for P/Invokes to ensure handles aren't accidentally freed before unmanaged code is done with them.
When is an IntPtr
a handle that could be wrapped by SafeHandle
? You won't be able to tell from the IntPtr
, you have to know what function is returning the IntPtr
. It will document whether or not you're dealing with a handle and if so, how you should close the handle when you're done with it (very often, but by no means always, CloseHandle
). If you only have a P/Invoke signature, then technically, you have nothing. In particular, it will not be possible to determine what function should be called to free the handle, if it is a handle. An IntPtr
can also be used to marshal PVOID
or SIZE_T
or P<some_struct>
(even though out
or ref
parameters are more natural for that) or any other type that's supposed to be pointer-sized.
Any handle-as-IntPtr
that escapes beyond a single function (especially one stored in a field) is a really good candidate for a SafeHandle
wrapper, as is any use of multiple IntPtr
s at the same time (to prevent accidentally mixing up incompatible handles). For a simple one-off that involves no multithreading and doesn't let the handle escape beyond its scope, a try .. finally
block is probably enough. If you want, everything can be wrapped in a SafeHandle
for consistency's sake (or to explicitly document what object type you're dealing with), but that doesn't necessarily lead to better results. Handle recycling is a serious issue, but not a concern here since the handle is to local memory, and reliability isn't an issue because any problem serious enough to bypass a finally
block is also serious enough to make a small memory leak a non-issue.
Your particular scenario (parsing SDDL into a security descriptor) is already implemented in the framework in the form of RawSecurityDescriptor
, which you should consider using in favor of reinventing the wheel (and/or implementing your own SecurityDescriptor
subclass if it's not already covered by the existing classes in System.Security.AccessControl
. For what it's worth, RawSecurityDescriptor
also P/Invokes to ConvertStringSecurityDescriptorToSecurityDescriptorW
and doesn't bother with a SafeHandle
. Framework code should not necessarily be treated as a good example of what to do (plenty of code violates the official guidelines), but it's something.