我的 d3d11 c++ 代码对我从未初始化过的实时 COM 对象产生警告。
我的代码:
#define _INCLUDE_LIBS__
#include "stdafx.h"
#define WINDOW_NAME L"main window"
#define WS WS_OVERLAPPEDWINDOW
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
HWND hwnd = NULL; {
WNDCLASS wc = { 0 };
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 1));
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = L"MainClass";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClass(&wc)) OutputDebugString(L"ERROR : window class registration failed!");
hwnd = CreateWindow(wc.lpszClassName, WINDOW_NAME, WS, 0, 0, 1000, 600, NULL, NULL, hInstance, NULL);
if(!hwnd) OutputDebugString(L"ERROR : window Creation failed!");
}
IDXGIFactory1* factory = nullptr; {
CreateDXGIFactory1(IID_PPV_ARGS(&factory));
}
IDXGIAdapter* adapter = nullptr; {
factory->EnumAdapters(0, &adapter);
DXGI_ADAPTER_DESC desc;
adapter->GetDesc(&desc);
OutputDebugString(L"\n");
OutputDebugString(desc.Description);
OutputDebugString(L"\n\n");
}
ID3D11Device* device = nullptr; ID3D11DeviceContext* context = nullptr; {
D3D_FEATURE_LEVEL lvl[] = { D3D_FEATURE_LEVEL_10_0 };
UINT flag = D3D11_CREATE_DEVICE_DEBUG;
D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flag, lvl, ARRAYSIZE(lvl), D3D11_SDK_VERSION, &device, NULL, &context);
}
ID3D11Debug* debug = nullptr; {
device->QueryInterface(IID_PPV_ARGS(&debug));
}
if (context) context->Release();
if (device) device->Release();
if (adapter) adapter->Release();
if (factory) factory->Release();
debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
但这会产生警告:
D3D11 WARNING: Live ID3D11Device at 0x0000020454692FF0, Refcount: 2 [ STATE_CREATION WARNING #441: LIVE_DEVICE]
D3D11 WARNING: Live ID3D11Context at 0x0000020454695020, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #2097226: LIVE_CONTEXT]
D3D11 WARNING: Live ID3DDeviceContextState at 0x000002045626F000, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #3145742: LIVE_DEVICECONTEXTSTATE]
D3D11 WARNING: Live ID3D11BlendState at 0x0000020456266170, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #435: LIVE_BLENDSTATE]
D3D11 WARNING: Live ID3D11DepthStencilState at 0x0000020456266370, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #436: LIVE_DEPTHSTENCILSTATE]
D3D11 WARNING: Live ID3D11RasterizerState at 0x0000020456266570, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #437: LIVE_RASTERIZERSTATE]
D3D11 WARNING: Live ID3D11Sampler at 0x0000020456266780, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #434: LIVE_SAMPLER]
D3D11 WARNING: Live ID3D11Query at 0x0000020456266E60, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #438: LIVE_QUERY]
我不知道为什么那些额外的对象会被初始化。我在设备上进行了两次发布,似乎再次一切正常,但我也不知道发生了这种情况。
我想知道我是否在某个地方犯了错误,因为我不知道COM内部是如何工作的,甚至一点点我只知道我创建了对象,我释放了对象。
是的,我不知道为什么会发生这种情况,有人可以解释一下为什么会发生这种情况以及我应该做什么来解决这个问题吗?
我使用的是 Visual Studio Community 2019,操作系统:Windows 64 位
你的代码很好(只是不要忘记也做
debug->Release
)。
refcount = 0 行非常无用,它们不是泄漏,并且这里显然是由内部 D3D11 代码创建的(您不创建混合状态等)。
您还可以使用
D3D11_RLDO_DETAIL | D3D11_RLDO_IGNORE_INTERNAL
删除其中一些。
现在,使用此 API 因显示误报而臭名昭著,“处于边缘”。经验表明,在退出之前,设备上通常会出现 1 或 2 次泄漏(可能是某些内部缓存在起作用)。 一般来说,当
ReportLiveDeviceObjects
结果显示很大的数字时,你真的要担心,比如你得到了 40 个对某个东西的引用,而它应该是 0,即:这个 API 仍然有用。
但是,当您使用 COM 对象时,我强烈建议您使用任何类型的智能指针技术,包括 ATL
CComPtr
(使用 Visual Studio)、WIL com_ptr
、C++/WinRT com_ptr
等等,这是避免 COM 引用泄漏的最佳方法。
例如,此代码 100% 无泄漏 (ATL):
CComPtr<IDXGIFactory> factory;
CreateDXGIFactory(IID_PPV_ARGS(&factory));
CComPtr<IDXGIAdapter> adapter;
factory->EnumAdapters(0, &adapter);