ITypeLib:GetLibAttr 和 ReleaseTLibAttr
ITypeLib: GetLibAttr and ReleaseTLibAttr
问题: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 also copies the structure。
你的代码没有问题。
您可以在 https://github.com/alexhenrie/wine/blob/master/dlls/oleaut32/typelib.c - ITypeLib2_fnGetLibAttr.
查看 GetLibAttr 的源代码
由于您已经加载了 TypeLib,因此 guid、lcid、syskind、wMajorVerNum、wMinorVerNum、wLibFlags 不能更改,直到下一次加载 TLB 文件并且仅在该文件被更改的情况下。
问题: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 also copies the structure。
你的代码没有问题。
您可以在 https://github.com/alexhenrie/wine/blob/master/dlls/oleaut32/typelib.c - ITypeLib2_fnGetLibAttr.
查看 GetLibAttr 的源代码
由于您已经加载了 TypeLib,因此 guid、lcid、syskind、wMajorVerNum、wMinorVerNum、wLibFlags 不能更改,直到下一次加载 TLB 文件并且仅在该文件被更改的情况下。