c – 有人可以解释为什么我在发布指向它们之后仍然有活动对象吗
我正在尝试单例模式,以便更容易使用DirectX API的一些常见接口,但我有一个我似乎无法解决的问题.
这是我的定义: #include <d3d11.h> #include <d3dx11.h> #include <DxErr.h> #pragma comment(lib,"d3d11.lib") #pragma comment(lib,"d3dx11.lib") #pragma comment(lib,"DxErr.lib") class Core { public: ~Core(); static ID3D11Device*& getDevice(); static ID3D11DeviceContext*& getContext(); static IDXGISwapChain*& getSwapChain(); static ID3D11RenderTargetView*& getRenderTargetView(); static ID3D11Debug*& getDebug(); static HRESULT Initialize(HWND hwnd); static void Reset(); private: Core(); HRESULT CreateDevice(); static Core* instance; ID3D11Device* device; ID3D11DeviceContext* context; IDXGISwapChain* swapChain; IDXGIDevice1* ddevice; IDXGIAdapter1* adapter; IDXGIFactory1* factory; ID3D11RenderTargetView* rtv; ID3D11Debug* debug; Core(Core const&); void operator=(Core const&); }; 这是实施: #include "Core.h" Core* Core::instance; Core::Core() { HRESULT hr; hr = CreateDevice(); if(FAILED(hr)) throw hr; } Core::~Core() { if (device) device->Release(); if (context) context->Release(); if (swapChain) swapChain->Release(); if (ddevice) ddevice->Release(); if (adapter) adapter->Release(); if (factory) factory->Release(); if (rtv) rtv->Release(); debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL); } //-------------------------------------------------------------------------------- // Get Functions //-------------------------------------------------------------------------------- ID3D11Device*& Core::getDevice() { if (!instance) { try { instance = new Core(); } catch (HRESULT hr) { throw hr; } } return instance->device; } ID3D11DeviceContext*& Core::getContext() { if (!instance) { try { instance = new Core(); } catch (HRESULT hr) { throw hr; } } return instance->context; } IDXGISwapChain*& Core::getSwapChain() { if (!instance) { try { instance = new Core(); } catch (HRESULT hr) { throw hr; } } return instance->swapChain; } ID3D11RenderTargetView*& Core::getRenderTargetView() { if (!instance) { try { instance = new Core(); } catch (HRESULT hr) { throw hr; } } return instance->rtv; } ID3D11Debug*& Core::getDebug() { if (!instance) { try { instance = new Core(); } catch (HRESULT hr) { throw hr; } } return instance->debug; } //-------------------------------------------------------------------------------- // Other Functions //-------------------------------------------------------------------------------- HRESULT Core::CreateDevice() { D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0,D3D_FEATURE_LEVEL_10_1,D3D_FEATURE_LEVEL_10_0,}; D3D_FEATURE_LEVEL featureLevel; UINT flags = NULL; #ifdef _DEBUG flags |= D3D11_CREATE_DEVICE_DEBUG; #endif HRESULT hr; hr = D3D11CreateDevice( NULL,D3D_DRIVER_TYPE_HARDWARE,NULL,flags,featureLevels,ARRAYSIZE(featureLevels),D3D11_SDK_VERSION,&device,&featureLevel,&context); if(FAILED(hr)) return hr; hr = device->QueryInterface(__uuidof(ID3D11Debug),(void**) &debug); if(FAILED(hr)) return hr; hr = device->QueryInterface(__uuidof(IDXGIDevice1),(void**) &ddevice); if(FAILED(hr)) return hr; hr = ddevice->GetParent(__uuidof(IDXGIAdapter1),(void**) &adapter); if(FAILED(hr)) return hr; hr = adapter->GetParent(__uuidof(IDXGIFactory1),(void**) &factory); if(FAILED(hr)) return hr; return S_OK; } HRESULT Core::Initialize(HWND hwnd) { // Create the swap chain RECT rc; GetClientRect(hwnd,&rc); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; DXGI_SWAP_CHAIN_DESC sd; ZeroMemory( &sd,sizeof( sd ) ); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = hwnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; if (!instance) { try { instance = new Core(); } catch (HRESULT hr) { return hr; } } instance->factory->CreateSwapChain(instance->device,&sd,&instance->swapChain); // Create and set the render target view HRESULT hr; ID3D11Texture2D* renderingBuffer; hr = instance->swapChain->GetBuffer(0,__uuidof(ID3D11Texture2D),(void**) &renderingBuffer); if(FAILED(hr)) { renderingBuffer->Release(); return hr; } hr = instance->device->CreateRenderTargetView(renderingBuffer,&instance->rtv); renderingBuffer->Release(); if(FAILED(hr)) return hr; // TODO: create and set the depth stencil view instance->context->OMSetRenderTargets(1,&instance->rtv,nullptr); return S_OK; } void Core::Reset() { delete instance; } 析构函数被调用,但是一旦我退出应用程序,我仍然会在输出窗口中看到这个: D3D11 WARNING: Live ID3D11Device at 0x007A201C,Refcount: 2 [ STATE_CREATION WARNING #441: LIVE_DEVICE] D3D11 WARNING: Live ID3D11Context at 0x007A3620,Refcount: 0,IntRef: 1 [ STATE_CREATION WARNING #2097226: LIVE_CONTEXT] D3D11 WARNING: Live ID3DDeviceContextState at 0x007ADBB0,IntRef: 1 [ STATE_CREATION WARNING #3145742: LIVE_DEVICECONTEXTSTATE] D3D11 WARNING: Live ID3D11BlendState at 0x007B3D84,IntRef: 1 [ STATE_CREATION WARNING #435: LIVE_BLENDSTATE] D3D11 WARNING: Live ID3D11DepthStencilState at 0x007B3ECC,IntRef: 1 [ STATE_CREATION WARNING #436: LIVE_DEPTHSTENCILSTATE] D3D11 WARNING: Live ID3D11RasterizerState at 0x007B403C,IntRef: 1 [ STATE_CREATION WARNING #437: LIVE_RASTERIZERSTATE] D3D11 WARNING: Live ID3D11Sampler at 0x007B428C,IntRef: 1 [ STATE_CREATION WARNING #434: LIVE_SAMPLER] D3D11 WARNING: Live ID3D11Query at 0x007B440C,IntRef: 1 [ STATE_CREATION WARNING #438: LIVE_QUERY] D3D11 WARNING: Live IDXGISwapChain at 0x007B45B8,Refcount: 0 [ STATE_CREATION WARNING #442: LIVE_SWAPCHAIN] D3D11 WARNING: Live ID3D11Texture2D at 0x007B4B1C,IntRef: 1 [ STATE_CREATION WARNING #425: LIVE_TEXTURE2D] D3D11 WARNING: Live ID3D11RenderTargetView at 0x007B4EBC,IntRef: 0 [ STATE_CREATION WARNING #428: LIVE_RENDERTARGETVIEW] D3D11 WARNING: Live ID3D11Texture2D at 0x007B55EC,IntRef: 1 [ STATE_CREATION WARNING #425: LIVE_TEXTURE2D] 我还检查了析构函数中的Release()函数是否实际被调用了. 我必须遗漏一些非常明显的东西,如果有人能指出我,我会非常感激. 另外,这是我使用单例模式在这种情况下做的聪明吗? 谢谢. 编辑: 这是我的DirectX类,我使用Core类: #include "DirectX.h" DirectX::DirectX() {} DirectX::DirectX(HWND hwnd) { HRESULT hr; hr = Init(hwnd); if(FAILED(hr)) throw hr; hr = Load(); if(FAILED(hr)) throw hr; } DirectX::~DirectX() { Core::Reset(); } HRESULT DirectX::Init(HWND hwnd) { HRESULT hr; hr = Core::Initialize(hwnd); if(FAILED(hr)) return hr; return S_OK; } HRESULT DirectX::Load() { return S_OK; } HRESULT DirectX::Update() { return S_OK; } HRESULT DirectX::Render() { try { float backgroundcolor[4] = {1.0f,1.0f,0.0f,1.0f}; Core::getContext()->ClearRenderTargetView(Core::getRenderTargetView(),backgroundcolor); Core::getSwapChain()->Present(0,0); } catch (HRESULT hr) { return hr; } return S_OK; } 解决方法
我很高兴你自己已经找到了答案,但是我可以给你一些关于单身模式和Cpp的建议吗?
对我来说,看起来你是从C背景转换到Cpp.我一直在为那些进行转换的团队审查很多代码,这看起来很熟悉我. 你在那里做的是没有单例模式(即使它有那个实例指针).您有一个指向实例的静态指针并不意味着所有方法都必须是静态的. – 你所做的是一个静态函数库,它对一个结构中的数据进行操作,而这个结构本身就是它自己的实例.你可能已经离开了这个类,将数据放在一个结构上,你将拥有与你几乎相同的东西. – 但是单身就是其中之一,它是一个用自己的方法操作的对象,就像你期望从一个对象那样的数据(比如家里唯一的,不可复制的咖啡机),而不是静态数据. Joachim Pileborg对指针的处理也是正确的,这很危险,因为任何人都可以在每次事故中分配另一个对象,留下泄露的记忆和其他影响会导致在较大的项目中很难找到错误.你应该只有一个非常好的理由这样做. 接下来,你应该在构造函数中为所有成员变量定义使用初始化列表,或者在构造函数中以另一种方式初始化它们,否则如果somemone获得一个实例并立即在你的类上调用Reset,则指针都是随机地址(不是0) ).意味着析构函数肯定会崩溃. 作为最后一个提示不要使用指针,因为你会在if语句中使用布尔值.你编写代码,你是一个作者,如果(obj == NULL)尝试清楚地沟通你在做什么. 像这样应用一个基本的单例模式(还有其他方法可以实现更优雅的实例化或线程保存,但这是基本模式): (注意我没有编译这个,因为我正在使用Linux机器atm,可能会出现问题,即如果在&Create;前面有一个& x,那么在CreateDevice()函数中,我没有检查这些) 祝你的项目好运! Core.h #include <d3d11.h> #include <d3dx11.h> #include <DxErr.h> #pragma comment(lib,"DxErr.lib") class Core { public: Core* instance(); static void Reset(); ~Core(); HRESULT Initialize(HWND hwnd); ID3D11Device* getDevice(); ID3D11DeviceContext* getContext(); IDXGISwapChain* getSwapChain(); ID3D11RenderTargetView* getRenderTargetView(); ID3D11Debug* getDebug(); private: static Core* instance; ID3D11Device* device; ID3D11DeviceContext* context; IDXGISwapChain* swapChain; IDXGIDevice1* ddevice; IDXGIAdapter1* adapter; IDXGIFactory1* factory; ID3D11RenderTargetView* rtv; ID3D11Debug* debug; HRESULT CreateDevice(); Core(); Core(Core const&); void operator=(Core const&); }; Core.cpp #include "Core.h" Core* Core::instance; Core* Core::instance() { if (instance == NULL) { try { instance = new Core(); } catch (HRESULT hr) { throw hr; } } } Core::Core() : device(NULL),context(NULL),swapChain(NULL),ddevice(NULL),adapter(NULL),factory(NULL),rtv(NULL),debug(NULL) { HRESULT hr; hr = CreateDevice(); if(FAILED(hr)) throw hr; } Core::~Core() { if (device != NULL) device->Release(); if (context != NULL) context->Release(); if (swapChain != NULL) swapChain->Release(); if (ddevice != NULL) ddevice->Release(); if (adapter != NULL) adapter->Release(); if (factory != NULL) factory->Release(); if (rtv != NULL) rtv->Release(); debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL); } ID3D11Device* Core::getDevice() { return this->device; } ID3D11DeviceContext* Core::getContext() { return this->context; } IDXGISwapChain* Core::getSwapChain() { return this->swapChain; } ID3D11RenderTargetView* Core::getRenderTargetView() { return this->rtv; } ID3D11Debug* Core::getDebug() { return this->debug; } HRESULT Core::CreateDevice() { D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0,sizeof( sd ) ); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = hwnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; this->factory->CreateSwapChain(this->device,this->swapChain); // Create and set the render target view HRESULT hr; ID3D11Texture2D* renderingBuffer; hr = this->swapChain->GetBuffer(0,(void**) &renderingBuffer); if(FAILED(hr)) { renderingBuffer->Release(); return hr; } hr = this->device->CreateRenderTargetView(renderingBuffer,this->rtv); renderingBuffer->Release(); if(FAILED(hr)) return hr; // TODO: create and set the depth stencil view this->context->OMSetRenderTargets(1,&this->rtv,nullptr); return S_OK; } void Core::Reset() { delete instance; } 用法 #include "DirectX.h" DirectX::DirectX() {} DirectX::DirectX(HWND hwnd) { HRESULT hr; hr = Init(hwnd); if(FAILED(hr)) throw hr; hr = Load(); if(FAILED(hr)) throw hr; } DirectX::~DirectX() { Core::instance()->Reset(); } HRESULT DirectX::Init(HWND hwnd) { HRESULT hr; hr = Core::instance()->Initialize(hwnd); if(FAILED(hr)) return hr; return S_OK; } HRESULT DirectX::Load() { return S_OK; } HRESULT DirectX::Update() { return S_OK; } HRESULT DirectX::Render() { try { Core* core = Core::instance(); float backgroundcolor[4] = {1.0f,1.0f}; core->ClearRenderTargetView(core->getRenderTargetView(),backgroundcolor); core->Present(0,0); } catch (HRESULT hr) { return hr; } return S_OK; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |