2

I know that modern Windows versions reclaim memory that was previously acquired with malloc, new and the like, after program termination, but what about COM objects? Should I call obj->Release() on them on program's exit, or will the system do this for me?

My guess it: it depends. For out of process COM, I should probably always call Release(), but for in-process COM, I think it really doesn't matter, because the COM objects die after program termination anyway.

Abel
  • 56,041
  • 24
  • 146
  • 247
  • 2
    Try to close your programs gracefully: i.e. balance all your AddRef() with Release(). – Bathsheba Dec 16 '13 at 15:59
  • 1
    While it might not be needed, it's always a good idea to clean up after yourself. – Some programmer dude Dec 16 '13 at 16:01
  • 1
    @Bathsheba/@Joachim: I would do so, but that doesn't really answer the question. What happens if I have an unbalanced COM call, i.e., without Release? I may be lazy, but if the objects have to stick around for the lifetime of the program, does it really matter? – Abel Dec 16 '13 at 16:02
  • 1
    @Abel: What if there's some finalization like writing changes on disk when the specific object has last `Release()` called? – sharptooth Dec 17 '13 at 07:23

3 Answers3

4

If you're in the process itself then yes you should as you might not know where the server is and the server could be out of proc. If you're in a DLL it becomes more complicated.

In a DLL you should UNLESS you receive a DLL_PROCESS_DETACH notification, in which case you should do absolutely nothing and just let the application close. This is because this notification is called during process teardown. As such it is too late to clean up at that point. The kernel may have already reclaimed the blocks you call release on.

Remember as a DLL writer there is nothing you can do if the process exits ungracefully, you can only do what you can within reason to clean up after yourself in a graceful exit.

One easy solution is to use smart COM Pointers everywhere, the ATL and WRL have implementations that work nicely and make it so you don't have to worry about it for the most part. Even if these are stored statically their destructors will be called before process teardown or DLL unload, thus releasing safely at a time when it is safe to do so.

So the short answer is If you can e.g. you should always call release if it is safe to do so. However there are times when it is not and you should most definitely NOT do anything.

Mgetz
  • 5,108
  • 2
  • 33
  • 51
  • Actually, this is for a DLL. Are you really saying I should _not_ call `Release()` in a `DLL_PROCESS_DETACH`? Same for `DLL_THREAD_DETACH`? It seems counter to what I'd expect (reason perhaps that DLL unloading on process end is not ordered?) – Abel Dec 16 '13 at 16:05
  • 2
    @Abel I pulled that from [Raymond Chen's blog](http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx). Basically because the process is exiting it can be assumed that any action at that point may cause undefined behavior – Mgetz Dec 16 '13 at 16:06
  • Going for your answer here, as you've provided the most thorough information, while in other answers, there's also a lot of valuable info. Thanks all! – Abel Dec 16 '13 at 16:56
3

Depending on the implementation of the underlying object, there may or may not be a penalty. The object may have state that persists beyond process shutdown. A persistent lock in a local database is the easiest example that comes to mind.

With that in mind, I say it's better to call Release just in case.

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • Yes, or a COM object that logs, may need to flush the current buffer, or otherwise it won't write the latest log statements. This kind-of contradicts the "do nothing" in `DLL_PROCESS_DETACH` from @Mgetz above. If it's just memory you need to free, it's one thing, but when the release-count gets to zero, some COM objects may still need to do something. – Abel Dec 16 '13 at 16:18
2
  • in-process COM object will die with the process
  • out-of-process reference will be released on timeout
    • poorly designed servers and clients might remain in bad state holding pointers to objects (typically proxies), that are not available any longer, being unable to see they are dead. being unable to get rid of them
    • it is always a good idea to release the pointers gracefully

If you don't release COM pointers properly, and COM activity included marshaling, you are very likely to have exceptions in CoUninitialze which are both annoying and/or can end up showing process crash message to the user.

Roman R.
  • 68,205
  • 6
  • 94
  • 158
  • Didn't think about marshaling and CoUnitialize, actually, but it makes sense. So, this too is an argument against "doing nothing" from [Raymond Chen's blog](http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx) when `DLL_PROCESS_DETACH` comes around (if the COM object is in the DLL). – Abel Dec 16 '13 at 16:20
  • 1
    @Abel actually it's not, you should have called release PRIOR to `DLL_PROCESS_DETACH` if you're calling it when the walls are coming down you should expect bad things to happen. Remember that `CoUninitialize` is called prior to process exit. – Mgetz Dec 16 '13 at 16:22
  • If one does not do any out-of-process COM, then using `SetErrorMode` to suppress messages and die immediately might be a good idea. Well, maybe not even good exactly, but at least making some sense to exit as soon as possible. I would anyway always prefer to release the pointers. After all, some COM object might would like to save its persistent state on last `Release`. – Roman R. Dec 16 '13 at 16:23
  • @Mgetz: but... that means I have to leave the cleanup to the caller of my DLL, which, as it comes, doesn't expose COM, but just uses COM. So I should probably add a cleanup-function that can be used in `SafePointer`-derivative or `using`-block in for instance C# – Abel Dec 16 '13 at 16:24
  • @Abel no it means you left your cleanup until it was too late. If the process doesn't exit gracefully there isn't much you can do, and it isn't your responsibility to clean up after the process only yourself if you can. If you read Raymond's article carefully you'll note that `DLL_PROCESS_DETACH` is called during teardown, and thus the state of the application's memory space is indeterminate as the kernel may have already reclaimed blocks, so memory you thought you had may already have been freed. – Mgetz Dec 16 '13 at 16:26
  • @Mgetz: perhaps you misunderstood my last comment. A DLL has no notion of lifetime, except for DLL attach/detach etc. So, a DLL that uses COM and that needs the COM ptr around between function calls, can only clean up with a specific cleanup function (to prevent the teardown on proc detach to make this too late, as you suggest). Not that bad a design choice, I think, there are more Win32 API functions that have a freeing counterpart to clean up. – Abel Dec 16 '13 at 16:34
  • 1
    @Abel if that's the case, I highly suggest you use a `ComPtr` class, they should be automatically cleaned up when their destructor is called, which in theory should be prior to DLL unload, even if they are stored staticly. – Mgetz Dec 16 '13 at 16:40