[英]C++ Directx Error: Access Violation, swapchain was nullptr
I'm trying to learn 3D Drawing with DirectX and i got this Code in a Tutorial, but every time i try and compile it, my compiler gives out a "Access Violation swapchain was nullptr" Error. 我正在尝试使用DirectX学习3D绘图,并且在教程中获得了此代码,但是每次尝试对其进行编译时,我的编译器都会出现“访问冲突swapchain was nullptr”错误。
Thanks in advance 提前致谢
// include the basic windows header files and the Direct3D header files
#include <windows.h>
#include <windowsx.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
// include the Direct3D Library file
#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dx10.lib")
// global declarations
IDXGISwapChain *swapchain; // the pointer to the swap chain interface
ID3D11Device *dev; // the pointer to our Direct3D device interface
ID3D11DeviceContext *devcon; // the pointer to our Direct3D device context
ID3D11RenderTargetView *backbuffer; // the pointer to our back buffer
// function prototypes
void InitD3D(HWND hWnd); // sets up and initializes Direct3D
void RenderFrame(void); // renders a single frame
void CleanD3D(void); // closes Direct3D and releases memory
// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = L"WindowClass";
RegisterClassEx(&wc);
RECT wr = {0, 0, 800, 600};
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
hWnd = CreateWindowEx(NULL,
L"WindowClass",
L"Our First Direct3D Program",
WS_OVERLAPPEDWINDOW,
300,
300,
wr.right - wr.left,
wr.bottom - wr.top,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, nCmdShow);
// set up and initialize Direct3D
InitD3D(hWnd);
// enter the main loop:
MSG msg;
while(TRUE)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if(msg.message == WM_QUIT)
break;
}
RenderFrame();
}
// clean up DirectX and COM
CleanD3D();
return msg.wParam;
}
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}
// this function initializes and prepares Direct3D for use
void InitD3D(HWND hWnd)
{
// create a struct to hold information about the swap chain
DXGI_SWAP_CHAIN_DESC scd;
// clear out the struct for use
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
// fill the swap chain description struct
scd.BufferCount = 1; // one back buffer
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = 1; // how many multisamples
scd.SampleDesc.Quality = 0; // multisample quality level
scd.Windowed = TRUE; // windowed/full-screen mode
// create a device, device context and swap chain using the information in the scd struct
D3D11CreateDeviceAndSwapChain(NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
NULL,
NULL,
NULL,
D3D11_SDK_VERSION,
&scd,
&swapchain,
&dev,
NULL,
&devcon);
// get the address of the back buffer
ID3D11Texture2D *pBackBuffer;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
// use the back buffer address to create the render target
dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
pBackBuffer->Release();
// set the render target as the back buffer
devcon->OMSetRenderTargets(1, &backbuffer, NULL);
// Set the viewport
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = 800;
viewport.Height = 600;
devcon->RSSetViewports(1, &viewport);
}
// this is the function used to render a single frame
void RenderFrame(void)
{
// clear the back buffer to a deep blue
devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));
// do 3D rendering on the back buffer here
// switch the back buffer and the front buffer
swapchain->Present(0, 0);
}
// this is the function that cleans up Direct3D and COM
void CleanD3D(void)
{
// close and release all existing COM objects
swapchain->Release();
backbuffer->Release();
dev->Release();
devcon->Release();
}
When programming COM APis like Direct3D, it's critical that you check the return value of all functions that return an HRESULT
. 当像Direct3D一样对COM AP进行编程时,检查返回HRESULT
的所有函数的返回值至关重要。 If it's safe to ignore the return value, then it will return void
. 如果可以安全地忽略返回值,则它将返回void
。
This means using the SUCCEEDED
or FAILED
macros on every HRESULT. 这意味着在每个HRESULT上使用SUCCEEDED
或FAILED
宏。 You should avoid doing == S_OK
or != S_OK
as there are success results other than S_OK
. 您应该避免执行== S_OK
或!= S_OK
因为除了S_OK
之外还有成功的结果。 With modern C++, an even better option is to use ThrowIfFailed for 'fatal fast fail' scenarios where your program cannot recover from a failure. 使用现代C ++,更好的选择是将ThrowIfFailed用于“致命的快速失败”方案,在这种情况下程序无法从失败中恢复。
Your code is also failing to check for a failure in the call to RegisterClassEx
or CreateWindowEx
which could result in the hWnd
being null before you really get started. 您的代码也无法检查对RegisterClassEx
或CreateWindowEx
的调用是否失败,这可能会导致hWnd
在您真正开始之前为null。
You should also consider using
nullptr
instead ofNULL
. 您还应该考虑使用nullptr
而不是NULL
。 You are passingNULL
in places that actually take aUINT
which only compiles since you are using the old-school preprocessor define for 0. 您正在实际使用UINT
位置传递NULL
,因为您使用的是老式的预处理器定义0,所以该位置只能编译。
Once you are checking the return values, the next step is to enable the debug device. 一旦检查了返回值,下一步就是启用调试设备。 See Anatomy of Direct3D 11 Create Device and Direct3D SDK Debug Layer Tricks . 请参见Direct3D剖析11创建设备和Direct3D SDK调试层技巧 。 The debug layer will provide additional information in the debug output window when returning common failures like E_INVALIDARG
. 当返回诸如E_INVALIDARG
常见故障时,调试层将在调试输出窗口中提供其他信息。
Note that BufferCount
needs to be at least 2. Anything below 1 is treated as 2 anyhow. 请注意, BufferCount
必须至少为2。无论如何,低于1的值都将被视为2。
Since you are new to Direct3D 11 programming, I recommend you take a look at the DirectX Tool Kit tutorials . 由于您是Direct3D 11编程的新手,因此建议您看一下DirectX Tool Kit教程 。
You should also initialize all variables. 您还应该初始化所有变量。
IDXGISwapChain *swapchain = nullptr;
ID3D11Device *dev = nullptr;
ID3D11DeviceContext *devcon = nullptr;
ID3D11RenderTargetView *backbuffer = nullptr;
You should really avoid using 'raw' pointers for COM objects. 您应该真正避免对COM对象使用“原始”指针。 A better choice is to use a COM smart-pointer like ComPtr . 更好的选择是使用ComPtr之类的COM智能指针。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.