在序列化與還原序列化中,我們經常使用CComVariant.ReadFromStream從一個資料流中讀取變數。常規的代碼如下:
HRESULT __PIMShell_AjaxList_Load(IStream* pStream)<br />{<br />...<br />CComVariant vValue=(bool)true;<br />...<br />HRESULT hr=vValue.ReadFromStream(pStream);<br />if(FAILED(hr))<br /> return hr;<br />...<br />}<br />
一般情況下,這段代碼可以很好的工作。但有時就會導致程式的崩潰。是什麼情況呢?我們來看一下:
情境:假定pStream中序列化了一個COM對象,我們需要把這個COM對象讀取到CComVariant變數vValue中。
1、vValue初始已儲存了其他值。如vValue.vt=VT_BOOL; vValue.boolVal=VARIANT_TRUE;
2、ReadFromStream內部先執行vValue.Clear()。 vValue.vt變為VT_EMPTY, vValue.boolVal值不變。
2、ReadFromStream內部再讀取VarType,結果vValue.vt為VT_DISPATCH。
3、ReadFromStream內部再讀取COM對象,出現了意外,沒有給vValue.pdispVal賦值,所以仍然是vValue.boolVal=VARIANT_TRUE。
4、當return hr時,自動執行vValue的析構方法,調用vValue.Clear()。因為當前vt等於VT_DISPATCH,所以會嘗試調用
vValue.pdispVal->Release(); 這時,vValue.pdispVal既不是NULL指標,也沒有指向一個有效介面指標。從而導致程式崩潰。
所以,更穩妥的代碼應該是這樣:
HRESULT __PIMShell_AjaxList_Load(IStream* pStream)<br />{<br />...<br />CComVariant vValue=(bool)true;<br />...<br />HRESULT hr=vValue.ReadFromStream(pStream);<br />if(FAILED(hr))<br />{<br /> //*** important<br /> ::VariantInit(&vValue);<br /> return hr;<br />}<br />...<br />}