Ultimately, you should always refer to the documentation, as rules for specific objects may differ from the norm. But in most cases, the following guidelines apply:
- Terminate should always be called if the object was properly initialized, and should be called before calling Release. Terminate often does last-minute cleanup work that cannot occur inside Release, such as synchronizing threads, or cleaning other objects that may have references back to this object. Failing to call Terminate could result in access violations as other threads continue to run, or could result in reference loops and leaks.
- Release should always be called when you’re discarding a reference to the object. Release should be called even if Terminate is also required.
Often, my cleanup code looks like this:
HRESULT hr = S_OK;
IWSDDeviceHost *pDeviceHost = NULL;
hr = WSDCreateDeviceHost( …, &pDeviceHost );
// …initialize and use pDeviceHost…
if( NULL != pDeviceHost )
// Always terminate pDeviceHost if it was successfully created/initialized
hr = pDeviceHost->Terminate();
// Optionally print an error if Terminate failed
// Always release pDeviceHost, even if Terminate failed
pDeviceHost = NULL;