2014-12-23 4 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).Нужно ли освобождать память WCHAR [], назначенной _variant_t?

http://roblocher.com/whitepapers/oletypes.html говорит, что варианты освободят назначенный ему BSTR, но в другой строке указано, что значения в указателе, назначенные _variant_t, должны быть освобождены вручную.

Нужно ли мне вручную освобождать myData или будет _variant_t позаботиться об этом?

+0

Вы пишете «указывая на PWCHAR (bstr)», но «PWCHAR» не совпадает с «BSTR». Их типы совместимы, но семантика отличается. –

ответ

2

Если вы посмотрите на деструктор _variant_t, вы увидите, что он вызывает API-интерфейс Windows VariantClear().

Однако конструктор _variant_t будет выделять для него новые данные. Поэтому, если вы используете его неправильно, вам может потребоваться удалить myData. В вашем текущем примере отображается указатель NULL. Это не очень полезно.

_variant_t будет выделять свои собственные данные и не имеет ничего общего с памятью, выделенной для myData. Если вы выделяете память для myData, вам придется освободить ее, потому что _variant_t собирается создать свою собственную копию.

+0

Больше говорит о том, что конструктор '_variant_t' говорит: [_variant_t (wchar_t * wstrSrc) Создает объект _variant_t типа VT_BSTR из строки Unicode. Выделяется новый BSTR.] (Http://msdn.microsoft.com/) ан-нас/библиотека/k74e1xsh.aspx)». Таким образом, копируется оригинал 'wchar_t *'. Вариант не указывает на 'myData'. Он указывает на копию 'myData'. Поэтому вы несете ответственность за освобождение 'myData'. –

+0

@RaymondChen Мы вручную удалили данные, выделенные освобождением it.second.bstr, но когда сам _variant_t вышел из области видимости, мы получили двойную свободную ошибку (когда у нас включен активатор). Теперь мы освободим его.second.bstr и установите it.second.vt = VT_EMPTY. Это остановило двойную свободную ошибку. –

+0

@GaneshR. Но это был не ваш вопрос. Ваш вопрос: «Нужно ли нам освобождать' WCHAR [] '?? И ответ: «Да, потому что' _variant_t' сделал его копию ». Но здесь вы говорите о «BSTR», это совсем другое дело. (Кроме того, вам не нужно освобождать 'it.second.bstr', он будет освобожден, когда' _variant_t' будет уничтожен. И даже если вы решите освободить его самостоятельно, убедитесь, что вы используете 'SysFreeString', а не 'delete []'.) –

2

VARIANT - тип взаимодействия, предназначенный для использования с разных языков, имеющих разные исполнения. В WCHAR * нет ничего взаимоисключающего, уничтожение строкового буфера нельзя сделать надежно, если потребитель не знает, какую кучу он выделил. Или, если это важно, если он даже хранится в куче или поступает из одного и того же процесса.

Таким образом, Windows предоставляет строковый тип, который гарантировал выделение и освобождение семантики, это BSTR. Основными вызовами winapi являются SysAllocString() и SysFreeString(). Хранение выделяется из выделенной кучи, из которой выделяется CoTaskMemAlloc(). Также используется SAFEARRAY, другой тип переменной длины, который требует одинаковых гарантий.

Таким образом, только способ, которым это может работать, заключается в том, что ваша строка скопирована. Выполняется конструктором _variant_t, который принимает const wchar_t *, он вызывает SysAllocString(). Поэтому вам нужно снова уничтожить свой строковый буфер, вы можете сделать это сразу же после того, как вы присвоили его варианту. Деструктор _variant_t выполняет автоматическое уничтожение копии.

+0

Согласен. Изменен мой код, чтобы освободить PWCHAR и оставить вариант в покое. –

Смежные вопросы