You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DX11中CreateTexture2D引发内存泄漏问题求助

DX11纹理创建导致内存暴涨的资源释放问题

我在将DX11帧转换为cv::Mat并放入ECAL消息缓冲区的过程中,通过性能分析发现CreateTexture2D处出现内存暴涨。我尝试过释放纹理、设备和上下文,刷新上下文,将相关操作封装到方法中(期望借助析构释放资源),也尝试过使用COM指针,但均未解决问题。请问如何让这些资源真正释放?是否存在强制释放内存的方法?

相关代码片段

flatbuffers::FlatBufferBuilder builder(1024);
D3D11_TEXTURE2D_DESC desc;

surfaceTexture->GetDesc(&desc);

D3D11_BOX my_box;
cv::Mat mat;
ID3D11Texture2D* myText;

my_box.front = 0;
my_box.back = 1;
my_box.left = 1600;
my_box.top = 480;
my_box.right = 2240;
my_box.bottom = -160;

desc.Width = 640;
desc.Height = 640;
desc.ArraySize = 1;
desc.BindFlags = 0;
desc.MiscFlags = 0;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.MipLevels = 1;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.Usage = D3D11_USAGE_STAGING;
auto d3dDevice2 = GetDXGIInterfaceFromObject<ID3D11Device>(m_device2);
d3dDevice2->GetImmediateContext(m_d3dContext2.put());
d3dDevice2->CreateTexture2D(&desc, NULL, &myText);
m_d3dContext2->CopySubresourceRegion(myText, D3D11CalcSubresource(0, 0, 1), 0, 0, 0, surfaceTexture.get(), 0, &my_box);
/*cv::directx::convertFromD3D11Texture2D(myText, mat);*/
d3dDevice2->Release();
m_d3dContext2->Flush();
m_d3dContext1->Flush();
m_d3dContext2->Release();
m_d3dContext2.get()->Flush();
m_d3dContext1.get()->Flush();
m_d3dContext2.get()->Release();

cv::cvtColor(mat, mat, cv::COLOR_RGBA2RGB);

auto byte_buffer = builder.CreateVector(mat.data, sizeof(mat.data));
auto mloc = Dx11::Frame::CreateFrame(builder, byte_buffer);

builder.Finish(mloc);
pub.Send(builder, -1);

解决方案

  • 核心问题:遗漏纹理资源的释放
    代码中myText是手动创建的裸COM指针,但全程没有调用myText->Release(),这是内存泄漏的直接原因。DX11的COM对象依赖引用计数,只有当计数归0时才会真正释放内存。

  • 修正资源释放逻辑

    1. 在使用完myText后立即释放:
      // 无论是否执行convertFromD3D11Texture2D,都要释放
      if (myText != nullptr) {
          myText->Release();
          myText = nullptr;
      }
      
    2. 避免重复释放COM对象:代码中多次调用m_d3dContext2->Release()和d3dDevice2->Release(),会导致引用计数异常。如果GetDXGIInterfaceFromObject已经为d3dDevice2增加了引用计数,只需调用一次Release()即可。
  • 正确使用COM智能指针
    改用Microsoft::WRL::ComPtr管理COM对象,避免手动调用Release():

    Microsoft::WRL::ComPtr<ID3D11Texture2D> myText;
    // 创建时传入指针地址
    d3dDevice2->CreateTexture2D(&desc, NULL, myText.GetAddressOf());
    

    智能指针会在超出作用域时自动递减引用计数,无需手动释放。

  • 关于强制内存释放
    Windows没有针对单个COM对象的强制释放API,资源释放完全依赖引用计数机制。可以尝试调用CoFreeUnusedLibraries()释放未被使用的COM库,但这不是针对单个对象的解决方案。如果需要确保D3D命令执行完毕,可以调用ID3D11DeviceContext::Finish()(注意该函数会阻塞线程,需谨慎使用)。

  • 额外优化点

    • 复用staging纹理:避免每次创建临时纹理,可提前初始化一个固定尺寸的纹理,仅在尺寸变化时重新创建,减少内存分配开销。
    • 清理无效的OpenCV操作:当前代码中注释了convertFromD3D11Texture2D,mat处于未初始化状态,后续调用cv::cvtColor会触发未定义行为,需删除或修正这部分逻辑。

内容的提问来源于stack exchange,提问作者Ryan Lewkowicz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 09:50:23