在这种情况下,DirectX COM 对象会出现内存泄漏



如果我有这样的类或结构:

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 的更多信息,请参阅此处。

最新更新