<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx</link><description>If you try to do too much, you can find yourself in trouble.</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474385</link><pubDate>Tue, 27 Sep 2005 17:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474385</guid><dc:creator>Frederik Slijkerman</dc:creator><description>It looks like you should bump the reference count in the destructor before the Save() call.&lt;br&gt;Something like:&lt;br&gt;&lt;br&gt;MyObject::~MyObject()&lt;br&gt;{&lt;br&gt;  assert(m_cRef == 0);&lt;br&gt;  m_cRef = 1; // Set refcount back to valid state for other function calls.&lt;br&gt;  if (m_fNeedSave) Save();&lt;br&gt;}&lt;br&gt;</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474393</link><pubDate>Tue, 27 Sep 2005 17:52:59 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474393</guid><dc:creator>Chris Becke</dc:creator><description>You can't do the cleanup in the destructor as you cannot guarantee that the external object - now that it has a reference -  won't hold onto it for a while - and that delete this is going to continue cleaning up your object regardless of any (now) oustanding references.&lt;br&gt;&lt;br&gt;</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474404</link><pubDate>Tue, 27 Sep 2005 18:17:32 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474404</guid><dc:creator>Centaur</dc:creator><description>C++ object destructors are very sensitive functions.&lt;br&gt;&lt;br&gt;According to the Holy Standard, Chapter 3.8, Verse 1, after the destructor has started running, the object is officially dead. Any and all operations on it as a whole are considered necrophily and may be punishable by Undefined Behavior.</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474405</link><pubDate>Tue, 27 Sep 2005 18:20:46 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474405</guid><dc:creator>Andy Walldorff</dc:creator><description>I don’t think the change to AddRef would work.  When the object is first constructed, the reference count should be 0 and AddRef should be called at some point (probably via QueryInterface) to increment the reference count.  If this is not done, then the reference will never go to 0 and the object is not deleted.  I guess that is one reason why ATL destructors are not virtual and the FinalRelease method is provided.</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474409</link><pubDate>Tue, 27 Sep 2005 18:22:56 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474409</guid><dc:creator>Paul C.</dc:creator><description>Wow, that is pretty freakish.  The best solution is probably to avoid doing anything other than memory deallocation in your destructor, and make sure it only gets called once.  To do that, in Release() if the reference count has gone to zero, set a flag that says you're in cleanup.  If that flag is set, don't initiate cleanup again.  So, you'd end up with a Release() that looks something like this:&lt;br&gt;&lt;br&gt;ULONG MyObject::Release()&lt;br&gt;{&lt;br&gt; LONG cRef, cCleanup;&lt;br&gt;&lt;br&gt; cRef = InterlockedDecrement(&amp;amp;m_cRef);&lt;br&gt; if (cRef == 0) {&lt;br&gt;  // Constructor sets cCleanup to zero&lt;br&gt;  cCleanup = InterlockedIncrement(&amp;amp;m_cCleanup);&lt;br&gt;  if (cCleanup == 1) {&lt;br&gt;    if (m_fNeedSave) Save();&lt;br&gt;    delete this;&lt;br&gt;  }&lt;br&gt; }&lt;br&gt; return cRef;&lt;br&gt;}&lt;br&gt;&lt;br&gt;Now, we can be certain that we only deallocate ourselves once.</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474425</link><pubDate>Tue, 27 Sep 2005 19:05:58 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474425</guid><dc:creator>memet</dc:creator><description> My guess would be to create an internal (COM) object to pass to the save method - if we must call the save method.&lt;br&gt; Somehow serialize our data, pass it to this temporary object and then call the SaveToStream on that object.&lt;br&gt;</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474440</link><pubDate>Tue, 27 Sep 2005 19:34:25 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474440</guid><dc:creator>Lewis Jones</dc:creator><description>I ran across this with a COM-like environment (Reference counted objects, interface-based accessor, just without MS's overhead... It was for a set of all inproc DLLs so marshalling wasn't necessary, also we were trying for cross-platform).&lt;br&gt;&lt;br&gt;Anyways, we had a strange sequence of strong references that caused the situation above. Our solution was in our implementation of the Release() method to set the reference count to something out-of-range (like -100) immediately prior to calling &amp;quot;delete this&amp;quot;.&lt;br&gt;&lt;br&gt;This way any AddRef()/Release() would not have any effect (we only cared if the reference count == 0).&lt;br&gt;&lt;br&gt;Not pretty, but it worked...</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474456</link><pubDate>Tue, 27 Sep 2005 19:57:29 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474456</guid><dc:creator>X</dc:creator><description>Calling functions that could fail from a destructor is a bad idea, not only in COM.  A Save() function falls in this category.  &lt;br&gt;&lt;br&gt;</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474457</link><pubDate>Tue, 27 Sep 2005 20:00:45 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474457</guid><dc:creator>Moasat</dc:creator><description>I think I would just find a better way to save the object rather than doing it in the destructor.  Especially if the code required to save it involved Addref'ing the object being deleted.  If the SetSite didn't require an interface to 'this', then there'd be no problem here.  I think, regardless of any type of refcnt hacks, handing out an interface pointer to 'this' from the destructor is a Very Bad Thing.</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474479</link><pubDate>Tue, 27 Sep 2005 20:40:50 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474479</guid><dc:creator>Eric Lippert</dc:creator><description>VBScript needed to be designed around this exact issue.&lt;br&gt;&lt;br&gt;&lt;a rel="nofollow" target="_new" href="http://blogs.msdn.com/ericlippert/archive/2004/12/22/330276.aspx"&gt;http://blogs.msdn.com/ericlippert/archive/2004/12/22/330276.aspx&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;a rel="nofollow" target="_new" href="http://blogs.msdn.com/ericlippert/archive/2004/12/29/344074.aspx"&gt;http://blogs.msdn.com/ericlippert/archive/2004/12/29/344074.aspx&lt;/a&gt;&lt;br&gt;&lt;br&gt;</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474480</link><pubDate>Tue, 27 Sep 2005 20:43:11 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474480</guid><dc:creator>rburhum</dc:creator><description>&amp;gt;When the object is first constructed, the    reference count should be 0 and AddRef should be  called at some point (probably via  QueryInterface) to increment the reference count.&lt;br&gt;&lt;br&gt;Although I agree with you that this wouldn't work, I wanted to point out that I have seen implementations of an Unknown object that start with a reference count of 1 - this is not too uncommon.&lt;br&gt;&lt;br&gt;Another solution would be to model the save behavior with finer grained granularity; an explicit call to Save() before you reach the destructor.&lt;br&gt;&lt;br&gt;Either way... do I sense a series of articles on COM? I can't wait!</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474485</link><pubDate>Tue, 27 Sep 2005 20:50:31 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474485</guid><dc:creator>rburhum</dc:creator><description>&amp;gt; If the SetSite didn't require an interface to 'this', then there'd be no problem here. I think, regardless of any type of refcnt hacks, handing out an interface pointer to 'this' from the destructor is a Very Bad Thing.&lt;br&gt;&lt;br&gt;Handing out pointers to 'this' is not necessarily a &amp;quot;bad thing&amp;quot; or hack. In fact, this is very common with event sink objects and such kind of COM objects. </description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474512</link><pubDate>Tue, 27 Sep 2005 21:58:01 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474512</guid><dc:creator>Moasat</dc:creator><description>&amp;gt; Handing out pointers to 'this' is not necessarily a &amp;quot;bad thing&amp;quot; or hack. In fact, this is very common with event sink objects and such kind of COM objects.&lt;br&gt;&lt;br&gt;I was referring to the idea of handing it out from within the destructor and the 'hacks' of playing with the refcnt so that the destructor is not called twice.  While it might not directly be a bad thing, it could lead to bad things and is not very nice for any other developers to have to maintain.&lt;br&gt;&lt;br&gt;If I was working on a 'SetSite'-type function, I certainly wouldn't want to have to deal with the fact that the interface I'm getting may point to an object that is being destroyed.&lt;br&gt;&lt;br&gt;Alternatively, if I was working on the object being destroyed, I would question code that looked like this:&lt;br&gt;&lt;br&gt;if (refcnt &amp;lt; 0) ...  &lt;br&gt;&lt;br&gt;or&lt;br&gt;&lt;br&gt;if (refcnt == -100) ...&lt;br&gt;&lt;br&gt;</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474593</link><pubDate>Wed, 28 Sep 2005 00:57:31 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474593</guid><dc:creator>waleri</dc:creator><description>ULONG CMyObject::Release(void)&lt;br&gt;{&lt;br&gt;  assert(0 != m_cRef); // Somebody calling us twice?&lt;br&gt;&lt;br&gt;  if (1 == m_cRef) // Time to save, we're about to be destroyed&lt;br&gt;    Save();&lt;br&gt;&lt;br&gt;  // Save() could increase the counter&lt;br&gt;  LONG cRef = InterlockedDecrement(&amp;amp;m_cRef);&lt;br&gt;  if (0 == cRef) &lt;br&gt;    delete this;&lt;br&gt;&lt;br&gt;  return cRef;&lt;br&gt;}&lt;br&gt;</description></item><item><title>C++ Destructor Behavior</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474613</link><pubDate>Wed, 28 Sep 2005 01:35:38 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474613</guid><dc:creator>ipoverscsi</dc:creator><description>I've done some research into C++ destructors (on my own geek time), and using AddRef() in the destructor is just bad business.  &lt;br&gt;&lt;br&gt;Classes with virtual methods use a vtable to determine which methods to call at runtime.  In most C++ implementations the vtable is actually changed as the destructor deletes from most derived to base class; this is to ensure that base classes calling virtual methods to not access methods or fields of derived classes that have already been destroyed.  This means that even you somehow manage to prevent the memory from being reclaimed by the memory manager, virtual functions will only call the root classes methods.&lt;br&gt;</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#474681</link><pubDate>Wed, 28 Sep 2005 04:58:46 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474681</guid><dc:creator>Joe Beda</dc:creator><description>My favorite is a component that pushed a message loop during the final release.  The component in question will remain nameless...</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#475439</link><pubDate>Thu, 29 Sep 2005 23:00:24 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:475439</guid><dc:creator>abc</dc:creator><description>All the discussions do prove that &amp;quot;COM object destructors are very sensitive functions&amp;quot;.&lt;br&gt;&lt;br&gt;At least it's as same sensitve as ctr and dtr.</description></item><item><title>re: COM object destructors are very sensitive functions</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#475598</link><pubDate>Fri, 30 Sep 2005 09:12:05 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:475598</guid><dc:creator>autist0r</dc:creator><description>What about NOT saving in the destructor? I find it cleaner and more flexible to have an explicit call to save rather than an automatic save. Ok, sometimes it's not your choice...</description></item><item><title>Code  &amp;raquo; Blog Archive   &amp;raquo; Adding reference counting to something.</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#1857413</link><pubDate>Sun, 11 Mar 2007 10:50:31 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1857413</guid><dc:creator>Code  » Blog Archive   » Adding reference counting to something.</dc:creator><description>&lt;p&gt;PingBack from &lt;a rel="nofollow" target="_new" href="http://www.antcassidy.com/code/?p=44"&gt;http://www.antcassidy.com/code/?p=44&lt;/a&gt;&lt;/p&gt;
</description></item><item><title>Code  &amp;raquo; Blog Archive   &amp;raquo; My first use of CComObjectStackEx</title><link>http://blogs.msdn.com/oldnewthing/archive/2005/09/27/474384.aspx#1857509</link><pubDate>Sun, 11 Mar 2007 11:16:10 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1857509</guid><dc:creator>Code  » Blog Archive   » My first use of CComObjectStackEx</dc:creator><description>&lt;p&gt;PingBack from &lt;a rel="nofollow" target="_new" href="http://www.antcassidy.com/code/?p=8"&gt;http://www.antcassidy.com/code/?p=8&lt;/a&gt;&lt;/p&gt;
</description></item></channel></rss>