원래 평소에는 Debug 모드에서 위와 같이 깔끔하게 종료되는데
실수로 ID3D11Buffer 객체 하나를 Release 를 빼먹어서
Reference Count 가 하나 남게 되었고
아래처럼 회수 하지 않은 COM 객체가 남았다고 알려주는데 문제는
아래 내용을 보고서는 도저히 어떤 객체가 남았는지 알 수 없었다
그래서 열심히 구글링 하면서 찾아본 끝에
그나마 쉽게 추적할 수 있는 방법을 알아냈다
//WinMain
#ifdef _DEBUG
void D3D메모리누수체크()
{
HMODULE dxgidebugdll = GetModuleHandleW(L"dxgidebug.dll");
decltype(&DXGIGetDebugInterface) GetDebugInterface = reinterpret_cast<decltype(&DXGIGetDebugInterface)>(GetProcAddress(dxgidebugdll, "DXGIGetDebugInterface"));
IDXGIDebug* debug;
GetDebugInterface(IID_PPV_ARGS(&debug));
OutputDebugStringW(L"▽▽▽▽▽▽▽▽▽▽ Direct3D Object ref count 메모리 누수 체크 ▽▽▽▽▽▽▽▽▽▽▽\r\n");
debug->ReportLiveObjects(DXGI_DEBUG_D3D11, DXGI_DEBUG_RLO_DETAIL);
OutputDebugStringW(L"△△△△△△△△△△ 반환되지 않은 IUnknown 객체가 있을경우 위에 나타납니다. △△△△△△△△△△△△\r\n");
debug->Release();
}
#endif
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// System 객체 생성
SystemClass_10* System = new SystemClass_10;
if (!System)
{
return -1;
}
// System 객체 초기화 및 실행
if (System->Initialize())
{
System->Run();
}
// System 객체 종료 및 메모리 반환
System->Shutdown();
SAFE_DELETE(System);
#ifdef _DEBUG
D3D메모리누수체크();
#endif
return 0;
}
win 메인 함수가 있는 cpp 파일에 D3D메모리누수체크() 함수를 위와 같이 정의하고 return 0; 바로 위에서 호출한다
물론 위의 "D3D메모리누수체크" 같은 한글이름은 안써도 된다, 알아보기 쉽게 한글로 써놓은 것이다, 위의 참고자료 글에서는 list_remaining_d3d_objects() 라고 함수이름을 지었다
그 다음 Debug 모드로 실행뒤 종료하고 Output 창을 좀 올려다 보면
위와 같이 나타난다,
위 내용은 사실 위 코드의 D3D메모리누수체크() 함수안에 아래와 같은 부분이 실행된것이다
OutputDebugStringW(L"▽▽▽▽▽▽▽▽▽▽ Direct3D Object ref count 메모리 누수 체크 ▽▽▽▽▽▽▽▽▽▽▽\r\n");
debug->ReportLiveObjects(DXGI_DEBUG_D3D11, DXGI_DEBUG_RLO_DETAIL);
OutputDebugStringW(L"△△△△△△△△△△ 반환되지 않은 IUnknown 객체가 있을경우 위에 나타납니다. △△△△△△△△△△△△\r\n");
OutputDebugStringW 의 내용은 사실 중요하지 않다, 필자는 일부러 알아보기 쉽게 한글과 특수문자로
"▽▽▽▽▽▽▽▽▽▽ Direct3D Object ref count 메모리 누수 체크 ▽▽▽▽▽▽▽▽▽▽▽\r\n"
위와 같이 써놨는데, 구지 이렇게 해놓지 않아도 된다
어쨋든 위 Output 내용을 다시 보면 ID3D11Buffer 객체가 반환되지 않은 것을 알 수 있다
그러나 여전히 어떤 ID3D11Buffer 객체인지는 알아보기 힘들다
그렇기 때문에
위와 같이 모든 D3D COM 객체를 초기화 할때 SetPrivateData 함수를 실행해서
각각의 D3DDebugObjectName 을 따로 지정해준다
필자는 D3D COM 객체가 어떤 클래스에 멤버 변수 일때는
"LightShaderClass::m_cameraBuffer"
와 같이 D3DDebugObjectName 을 지정해줬다
SetPrivateData(
WKPDID_D3DDebugObjectName,
sizeof("LightShaderClass::m_cameraBuffer") - 1, //끝자리 0을 제외한 문자열길이
"LightShaderClass::m_cameraBuffer"); // D3DDebugObjectName
위와 같이 지정해준뒤 다시 디버그 모드로 실행뒤 종료하고 Output 창을 살펴보면
위에 지정한 그대로 나오는 것을 알 수 있다
이제 어느 클래스의 어떤 COM 객체가 회수를 못했는지 알았으니, 코드를 다시 올바르게 수정하여
COM객체를 회수하도록 하고
다시 디버그 모드로 실행뒤 종료하고 Output 창을 살펴보면
위의 빨간색 사각형으로 표시된 부분에 이전과는 다르게 아무런 내용도 나타나지 않은걸 알 수 있다
즉 모든 COM 객체가 깔끔하게 회수 된것이다.
'GameProgramming > DirectX11' 카테고리의 다른 글
DirectX11 picking 구현중 버그 발견 및 수정 (0) | 2021.03.14 |
---|---|
DirectX11 Visual Studio Graphics Analyzer, 간단한 shader 코드 디버깅 (0) | 2021.02.24 |
DirectX11 텍스트 폰트 깨짐, 클라이언트 및 전체 윈도우 영역 정하기 (0) | 2021.02.10 |
DirectX11, Map 함수, E_INVALIDARG (0) | 2021.02.07 |
DirectX11 어처구니 없는 쉐이더 실수 (0) | 2020.05.29 |