Проблема: ITypeLib::GetLibAttr()
метод выделяет новый TLIBATTR
структура, требуя от меня позвонить ITypeLib::ReleaseTLibAttr()
? Это делает код слишком многословным на мой вкус, и он может привести к утечкам памяти, если его пропустить.
Если я кеширую результат, тогда звоню ReleaseTLibAttr()
Есть ли побочные эффекты или возможные подводные камни при использовании кэшированного значения?
Структура TLIBATTR — это просто набор простых значений:
typedef struct tagTLIBATTR
{
GUID guid;
LCID lcid;
SYSKIND syskind;
WORD wMajorVerNum;
WORD wMinorVerNum;
WORD wLibFlags;
} TLIBATTR;
Нет членов, которые сами распределяются динамически. Возможно, это может быть изменено?
Я написал простой вспомогательный метод, чтобы предотвратить необходимость вызова ReleaseTLibAttr()
,
HRESULT MyGetLibAttr(ITypeLib* pTypeLib, TLIBATTR *pTLibAttr)
{
TLIBATTR *pTLibAttrTemp;
HRESULT hr = pTypeLib->GetLibAttr( &pTLibAttrTemp );
if ( SUCCEEDED(hr) )
{
memcpy( pTLibAttr, pTLibAttrTemp, sizeof(TLIBATTR) );
pTypeLib->ReleaseTLibAttr( pTLibAttrTemp );
}
return hr;
}
void main()
{
ITypeLib *pTypeLib;
HRESULT hr = LoadTypeLibEx( ... , &pTypeLib);
if ( SUCCEEDED(hr) )
{
TLIBATTR libAttr;
hr = MyGetLibAttr( pTypeLib, &libAttr );
if ( SUCCEEDED(hr) )
{
// Now we have a TLIBATTR object that we don't have to free.
}
pTypeLib->Release();
}
}
По шкале от 1 до 10, как будущее будущее MyGetLibAttr()
(обработка ошибок в стороне)? Есть ли побочные эффекты от использования кэшированного результата?
Я понимаю, что есть небольшой удар по производительности (дополнительный вызов memcpy()
), но нас больше беспокоит обслуживание кода и утечки памяти.
Метод интерфейса был разработан таким образом еще в 1996 году, потому что они не хотели терять возможность добавлять членов в структуру. На самом деле этого не произошло, TLIBATTR был стабильным в течение 19 лет. И больше никогда не изменится, Microsoft отошла от формата .tlb и теперь использует формат .winmd.
Если вам станет лучше, то .NET Framework также копирует структуру.
В вашем коде нет ничего плохого.
Вы можете проверить исходный код GetLibAttr на https://github.com/alexhenrie/wine/blob/master/dlls/oleaut32/typelib.c — ITypeLib2_fnGetLibAttr.
Поскольку вы загрузили TypeLib, то guid, lcid, syskind, wMajorVerNum, wMinorVerNum, wLibFlags не могут быть изменены до следующей загрузки файла TLB и только в случае, если этот файл был изменен.