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时才会真正释放内存。修正资源释放逻辑
- 在使用完
myText后立即释放:// 无论是否执行convertFromD3D11Texture2D,都要释放 if (myText != nullptr) { myText->Release(); myText = nullptr; } - 避免重复释放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
相关产品推荐
相关产品推荐

