Use SafeHandle to encapsulate native resources
Use of IntPtr in managed code might indicate a potential security and reliability problem. All uses of IntPtr must be reviewed to determine whether use of a SafeHandle, or similar technology, is required in its place. Problems will occur if the IntPtr represents some native resource, such as memory, file handle, socket, and so on, that managed code is considered to own. That is, managed code is expected to release the resource and failure to do so would cause resource leakage.
In such scenarios, security or reliability problems will also exist if multithreaded access is allowed to the IntPtr and a way of releasing the resource represented by the IntPtr. These problems involve recycling of the IntPtr value on resource release while simultaneous use of the resource is being made on another thread, leading to race conditions where one thread can read or write data associated with the wrong resource. For example, if your type stores an OS handle as an IntPtr and allows users to call both Close and any other method using that handle simultaneously and without some kind of synchronization, then your code has a handle recycling problem.
This handle recycling problem causes data corruption and, frequently, a security vulnerability. SafeHandle and its sibling class CriticalHandle provide a mechanism for encapsulating a native handle to a resource so that such threading problems can be avoided. Additionally, you can use SafeHandle and its sibling class CriticalHandle for other threading issues, for example, to carefully control the lifetime of managed objects that contain a copy of the native handle over calls to native methods. In this situation, you can often remove calls to GC.KeepAlive. There are performance overheads implicit in when you use SafeHandle and, to a lesser degree, CriticalHandle, which can frequently be reduced through careful design.