如果我有这样的类或结构:
bool localScopeFunc()
{
bool result;
IDXGIFactory* pFactory;
IDXGIAdapter* pAdapter;
result = //Do something here with the objects
if (!result) return false;
result = //Do something here with the objects
if (!result) return false;
result = //Do something here with the objects
if (!result) return false;
// And so on......
//___Do cleanup here___//
pFactory->Release(); pFactory = nullptr;
pAdapter->Release(); pAdapter = nullptr;
return true; // If all passes
}
如果在此函数期间的任何时候某些内容失败并且返回 false,则它不会在最后进行清理,因此不会在任何对象上调用 ->Release()。 这是否意味着内存泄漏?
如果是这样,我无法找到可行的方法来做到这一点,因为有时我会有一个函数调用列表,在每个阶段初始化新的东西,如果我必须反向清理所有内容,它看起来像这样:
int main()
{
if (!initTime()) {return -1;}
if (!initD3D()) {shutDownTime(); return -2;}
if (!initCamera()) {shutDownD3D(); shutDownTime(); return -3;}
if (!initSound()) {shutDownCamera(); shutDownD3D(); shutDownTime(); return -3;}
if (!initPhysics()) {shutDownSound(); shutDownD3D(); shutDownTime(); return -4;}
// And so on.
return 0;
}
是的,它会泄漏,因为您跳过了清理。COM 对象使用引用计数,交易是计数必须准确,系统才能在正确的时间删除内存。
这里的解决方案实际上非常简单: 使用 Microsoft::WRL::ComPtr
.无论您如何离开范围,此智能指针都会在需要时调用 Release。
需要注意的另一件事是,COM 对象不会以布尔值的形式返回错误。它们是 HRESULT。您不应该忽略它们,因为如果函数返回 HRESULT,它可能会失败。您也不应该使用 == S_OK 之类的。您应该使用 FAILED
宏、SUCCEEDED
宏或类似 DX::ThrowIfFailed 的内容。
#include <wrl/client.h>
using Microsoft::WRL::ComPtr;
bool localScopeFunc()
{
ComPtr<IDXGIFactory> pFactory;
ComPtr<IDXGIAdapter> pAdapter;
HRESULT result = //Do something here with the objects
if (FAILED(result)) return false;
result = //Do something here with the objects
if (FAILED(result)) return false;
result = //Do something here with the objects
if (FAILED(result)) return false;
// And so on......
return true; // If all passes
}
有关使用 Comptr 的更多信息,请参阅此处。