2014-12-23 45 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并单独使用变体。 –

相关问题