com — утечка C ++ с кодом VARIANT / bstrVal

Проверка на утечку говорит мне, что у меня есть утечка памяти в памяти, которая выделена в следующем коде:

// Get the value from the object as a variant.
VARIANT vVal;
VariantInit ( &vVal );
hres = clsObj->Get ( fieldName.c_str(), 0, &vVal, 0, 0 );
if ( FAILED ( hres ) )
{
(... various cleanup / throw stuff ...)
}

// And get it as a wstring.
wstring val ( vVal.bstrVal );

(... do some standard, non-memory leaking stuff with the wstring ...)

// Clean up.
VariantClear ( &vVal );

«ClsObj» — это IWbemClassObject, который является интерфейсом Microsoft для WMI.

Конкретной строкой, которая выделяет утечку памяти, является строка «clsObj-> Get». Средство проверки утечки затем сообщает более конкретный код для самой утечки (то есть далее в трассировке стека во время выделения утечки памяти), для которой у меня нет исходного кода:

(ole32): (filename not available): CoRevokeMallocSpy
(OLEAUT32): (filename not available): GetErrorInfo
(OLEAUT32): (filename not available): SysAllocStringLen
(OLEAUT32): (filename not available): SysAllocString
(wbemcomn): (filename not available): CVar::SetBSTR
(wbemcomn): (filename not available): CVar::FillVariant
(fastprox): (filename not available): CWbemObject::Get

Таким образом, базовая BSTR в VARIANT vVal, похоже, просочилась. Но я делаю VariantClear … я должен сделать что-то еще?

Возможно, я просочилась в конструктор wstring? Но если так, я не понимаю. Я думал, что bstrVal по сути сводится к указателю на символ (или wchar или что-то еще); конструктор wstring должен просто скопировать с этого адреса, как если бы это был любой другой указатель, верно?

Это не так, как конструктор wstring берет на себя ответственность за очистку памяти, на которую изначально указывал vVal.bstrVal, как если бы он делал Detach () для некоторого COM-объекта с подсчетом ссылок, не так ли?

В случае, если это имеет значение, это в Visual C ++ 6.

6

Решение

Там может быть нет утечки! Увидеть эта статья Microsoft Ларри Остермана на эту тему который описывает нечто похожее на то, что вы видите:

Я нашел кучу утечек и исправил их, но одна из утечек, которую я просто не мог выяснить, обнаруживалась каждый раз, когда мы выделяли объект BSTR. […]

По сути, OLE кэширует все объекты BSTR, выделенные в процессе, чтобы позволить ему объединять вместе строки. В результате эти струны эффективно просочились «нарочно». […]

К счастью, есть способ отключить кэширование BSTR, просто установите переменную среды OANOCACHE в 1, прежде чем запускать приложение. Если ваше приложение является службой, то вам нужно установить OANOCACHE в качестве системной переменной среды (нижний набор переменных среды) и перезагрузить компьютер.

1

Другие решения

BSTR это два элемента данных. Это int у которого есть счетчик длины базовой строки, а также основной строки. Так что даже если у вас есть emtpy BSTR держа "", вы должны очистить его правильно перед назначением нового BSTR значение для этого. В противном случае, даже если вы освободите часть ‘string’, вы потеряете int элемент данных.

Я подозреваю, что у вас есть утечка fieldname.c_str (). Это, вероятно, создает BSTR в стеке, и это утекает.

Измените свой код, чтобы сделать это вместо этого:

CComBSTR tempBSTR = fieldName.c_str();
hres = clsObj->Get ( tempBSTR, 0, &vVal, 0, 0 );

Это как минимум позволит вам убедиться, что это не автоматическая сборка BSTR утечка по вашему вызову Get ().

Кстати, если вам нужно работать с BSTR, посмотрите на использование CComBSTR на своем месте. Это может помочь предотвратить основные утечки памяти.

0

По вопросам рекламы [email protected]