在这种情况下,DirectX COM 对象会发生内存泄漏吗?

Memory leak in this situation with DirectX COM objects?

如果我有一个 class 或这样的结构:

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
}

如果在此函数的任何时候出现故障并且它 returns 为假,它不会在最后进行清理,因此不会在任何对象上调用 ->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 对象不会 return 作为布尔值的错误。它们是 HRESULT。您不应该忽略它们,因为如果函数 return 是一个 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 的更多信息,请参阅 this