To the excellent members of the COM team:
I have one question with the “stabilization” technique introduced in Don Box’s book.
In functions like FinalConstruct(), the outer object might create inner aggregation objects. These inner objects in turn might need to QueryInterface() outer object for communication. On page 96 of Don’s book, the inner object queries the “truck” interface of the outer in the inner’s Initialize().
It is mentioned on page 96 that the Initialize() code might accidently call release on the outer object when the outer object still has ref count of zero, cause an error. To guard this, a pair of AddRef()/Release() is added around the creation of inner object (also on page 96), and is named “stabilization”.
The ATL source code followed this in the code for CComCreator, and debugging show that InternalAddRef() and InternalRelease() are called.
However, question is on the necessity of stabilization:
Line 8263 onwards in atlbase.h (VS2022) shows a canonical implementation of QueryInterface(), in which AddRef() is only called when the query is successful. Otherwise the returns never equal S_OK (at line 8289 hRes is default initialized to something like 0xcccccccc rather than 0(==S_OK)).
Hence if QueryInterface() is unsuccessful, AddRef() will not be called, but also the return would not be S_OK, and the m_pTruck->Release() code in Don’s page 96 code would not be called either, so there is no danger of accidently calling Release() on the outer object when its ref count is zero.
Could you provide more insights on why the stabilization pairs is required?
Customer