Анализатор обнаружил вызов функции 'SysFreeString' для объекта, тип которого отличен от 'BSTR'.
Функция 'SysFreeString' предназначена только для работы с типом 'BSTR'. Нарушение этого условия может привести к проблемам с освобождением памяти.
Рассмотрим простой синтетический пример:
#include <atlbase.h>
void foo()
{
CComBSTR str { L"I'll be killed twice" };
// ....
SysFreeString(str); //+V1066
}
Здесь в функцию 'SysFreeString' передаётся объект типа 'CComBSTR'. Этот класс является обёрткой над типом 'BSTR' и имеет перегруженный оператор неявного преобразования 'operator BSTR()', который возвращает указатель на обёрнутую BSTR-строку. Поэтому приведённый выше код скомпилируется без предупреждений.
Однако, этот код содержит ошибку. После того, как функция 'SysFreeString' освободит ресурс, принадлежащий объекту 'str', произойдет выход из области видимости, и будет вызван деструктор объекта 'str'. Деструктор произведёт повторное освобождение уже освобождённого ресурса, что приведет к неопределённому поведению.
Иногда подобное поведение может случиться даже при передаче в 'SysFreeString' именно объекта типа 'BSTR'. Например, PVS-Studio также выдаст предупреждение на такой код:
#include <atlbase.h>
void foo()
{
CComBSTR str = { L"a string" };
BSTR bstr = str;
str.Empty();
SysFreeString(bstr); //+V1066
}
Так как 'CComBSTR::operator BSTR()' возвращает указатель на собственное поле, после присвоения 'BSTR bstr = str;' оба объекта будут владеть одним и тем же ресурсом. Вызов метода 'str.Empty();' освободит этот ресурс, а 'SysFreeString(bstr)' попытается освободить уже освобождённый ресурс.
Одним из способов избежать общего владения ресурсом является создание копии или использование метода 'CComBSTR::Detach()'. Например, анализатор не будет выдавать предупреждение на следующий код:
#include <atlbase.h>
void foo()
{
CComBSTR ccombstr = { L"I am a happy CComBSTR" };
BSTR bstr1 = ccombstr.Copy();
SysFreeString(bstr1); // OK
BSTR bstr2;
ccombstr.CopyTo(&bstr2);
SysFreeString(bstr2); // OK
BSTR bstr3 = ccombstr.Detach();
SysFreeString(bstr3); // OK
}
Данная диагностика классифицируется как:
|