2014-12-23 88 views
2
std::map<int, _variant_t> myMap; 

PWCHAR myData= NULL; 
//Set myData to some value. 

myMap.insert(std::pair<enStoreArchive, _variant_t>(1, myData)); 

在上面的代碼示例中,我有一個包含指向PWCHAR(bstr)的變體的映射。我們是否需要釋放分配給_variant_t的WCHAR []的內存?

http://roblocher.com/whitepapers/oletypes.html表示變體將釋放分配給它的BSTR,但另一行表示分配給_variant_t的指針中的值需要手動釋放。

我是否需要手動釋放myData或將_variant_t照顧它?

+0

您寫的是「指向PWCHAR(bstr)」,但是「PWCHAR」與「BSTR」不同。它們的類型是兼容的,但語義不同。 –

回答

2

如果你看看_variant_t的析構函數,你會看到它調用了windows API VariantClear()。

但是,_variant_t的構造函數將爲它分配新數據。因此,如果您使用錯誤,則可能需要刪除myData。你當前的例子只顯示一個NULL指針。這根本沒有什麼幫助。

_variant_t將分配自己的數據,並且確實與分配給myData的內存無關。如果你爲myData分配內存,你將不得不釋放它 - 因爲_variant_t會自己創建副本。

+0

更有說服力的是'_variant_t'的構造函數說:「[_variant_t(wchar_t * wstrSrc)從一個Unicode字符串構造一個VT_BSTR類型的_variant_t對象,並分配一個新的BSTR。](http://msdn.microsoft.com/ EN-US /庫/ k74e1xsh.aspx)」。所以最初的'wchar_t *'被複制。該變體不指向'myData'。它指向一個'myData'的副本。因此,您有責任釋放'myData'。 –

+0

@RaymondChen我們通過釋放it.second.bstr來手動刪除分配的數據,但是當_variant_t本身超出範圍時,我們得到了一個雙免費錯誤(當我們啓用了appverifier時)。我們現在釋放it.second.bstr並設置它.second.vt = VT_EMPTY。這停止了​​雙重免費錯誤。 –

+0

@GaneshR。但那不是你的問題。你的問題是「我們是否需要釋放WCHAR []'?」答案是「是的,因爲'_variant_t'是它的副本。」但是在這裏你正在談論「BSTR」,這完全是另一回事。 (另外,你不需要釋放'it.second.bstr';當'_variant_t'被破壞時它將被釋放,即使你選擇自己釋放它,確保你使用了'SysFreeString'而不是'刪除[]'。) –

2

VARIANT是一種互操作類型,設計用於不同運行時實現的不同語言。關於WCHAR *沒有任何可互操作的東西,如果消費者不知道它被分配了什麼堆,那麼銷燬字符串緩衝區就無法可靠地完成。或者,如果它甚至存儲在堆上或來自同一進程。

因此Windows提供了一個保證了分配和釋放語義的字符串類型,它是BSTR。底層的winapi調用是SysAllocString()和SysFreeString()。存儲從CoTaskMemAlloc()分配的專用堆中分配。 SAFEARRAY也用於另一種需要相同保證的可變長度類型。

所以唯一可行的方法是你的字符串是複製。由使用const wchar_t *的_variant_t構造函數完成,它調用SysAllocString()。因此,您需要再次銷燬字符串緩衝區,您可以在將其分配給變體後立即執行。 _variant_t析構函數負責自動銷燬副本。

+0

同意。更改我的代碼以釋放PWCHAR並單獨使用變體。 –

相關問題