异常:设备为nullptr.D3D11中的读取访问违规



每个人。

两年前我写了一个小的3D场景,它只有1700行的源代码(不包括.h文件(。现在回到GitHub并运行我的应用程序,我发现调试模式中有一个非常有趣的bug。Debbuger在为顶点缓冲区调用CreateBuffer:时引发异常

auto result = device->CreateBuffer(&vertex_buffer_desc, &vertex_data, &vertex_buffer);
if(FAILED(result))
return false;

基本上,调试器说(d3d11(设备是nullptr,但事实并非如此,因为在非调试模式下运行,一切都很好。但是,当我在创建设备之前定义UINT create_device_flag = D3D11_CREATE_DEVICE_DEBUG;时,会抛出以下异常:读取访问冲突。设备为nullptr。几天后,我仍然无法找出问题所在,因为指针的定义顺序是正确的。

这是Main.cpp

#include <StdAfx.h>
#include <Window.h>
#include <FPSCamera.h>
#include <DirectInput8.h>
#include <D3D11Renderer.h>
#include <Terrain.h>
#include <TerrainShader.h>
using namespace bm;
int __stdcall WinMain(HINSTANCE, HINSTANCE, char*, int)
{
auto resource_directory_name = L"..\..\..\Resource\"s;
auto terrain_name = L"terrain"s;
auto dds_file_extension = L".dds"s;
auto hlsl_file_extension = L".hlsl"s;
std::wstring resources[] = {resource_directory_name + L"heightmap.bmp"s,
resource_directory_name + terrain_name + dds_file_extension,
resource_directory_name + terrain_name + L"_bump"s + dds_file_extension,
resource_directory_name + terrain_name + L"_vs"s + hlsl_file_extension,
resource_directory_name + terrain_name + L"_ps"s + hlsl_file_extension};
constexpr auto ENABLE_FULLSCREEN = false;
constexpr auto ENABLE_VSYNC = false;
constexpr auto SCREEN_WIDTH = 1366;
constexpr auto SCREEN_HEIGHT = 768;
auto window = std::make_shared<bm::Window>(SCREEN_WIDTH, SCREEN_HEIGHT, ENABLE_FULLSCREEN);
window->registerClass();
window->create();
auto d3d11_renderer = std::make_shared<bm::D3D11Renderer>(SCREEN_WIDTH, SCREEN_HEIGHT, ENABLE_FULLSCREEN, window->getHandle(), ENABLE_VSYNC);
// Exception is thrown in the following ponter, but d3d11 device should be already initialized.
auto terrain = std::make_shared<bm::Terrain>(d3d11_renderer->getDevice(), resources[0].c_str(), resources[1].c_str(), resources[2].c_str());
auto terrain_shader = std::make_shared<bm::TerrainShader>(d3d11_renderer->getDevice(), resources[3].c_str(), resources[4].c_str());
auto fps_camera = std::make_shared<bm::FPSCamera>(static_cast<float>(SCREEN_WIDTH),  static_cast<float>(SCREEN_HEIGHT));
fps_camera->setPosition(500.f, 75.f, 400.f);
fps_camera->setRotation(20.f, 30.f, 0.f); // in degree.
auto direct_input_8 = std::make_shared<bm::DirectInput8>(window->getHandle());
constexpr float CLEAR_COLOR[] = {0.84f, 0.84f, 1.f, 1.f};
while(window->update())
{
direct_input_8->update(fps_camera->getMoveLeftRight(), fps_camera->getMoveBackForward(), fps_camera->getYaw(), fps_camera->getPitch());
fps_camera->update();
d3d11_renderer->clearScreen(CLEAR_COLOR);
terrain->render(d3d11_renderer->getDeviceContext());
terrain_shader->render(d3d11_renderer->getDeviceContext(),
terrain->getIndexCount(),
fps_camera->getWorld(),
fps_camera->getView(),
fps_camera->getProjection(),
{0.82f, 0.82f, 0.82f, 1.0f},
{-0.0f, -1.0f, 0.0f},
terrain->getColorTexture(),
terrain->getNormalMapTexture());
d3d11_renderer->swapBuffers();
}
return 0;
}

p.S。我知道网站上有一篇6年前的文章:CreateBuffer抛出了一个";访问违规读取位置";但它几乎无法解释任何事情,因为我没有全局变量和指针。我想纠正我以前的错误,所以如果需要的话,我很乐意具体说明。

很抱歉,这都是抽象代码,所以我们看不到您调用D3D11CreateDevice的实际位置。

也就是说,你描述的症状听起来像是你的操作系统上没有安装正确的调试设备SDK层。您可能也无法从D3D11CreateDevice中检查FAILEDHRESULT。

DWORD createDeviceFlags = 0;
#ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;
D3D_FEATURE_LEVEL fl;
HRESULT hr = D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_HARDWARE,
nullptr, createDeviceFlags, nullptr,
0, D3D11_SDK_VERSION, &device, &fl, &context );
if (FAILED(hr))
...

在未安装调试设备SDK层的系统上,这将在_DEBUG中失败。

在Windows 8.x或Windows 10上,安装旧版DirectX SDK不会安装任何调试运行时

对于Windows 8.x,您可以通过安装Windows 8.x SDK或Windows 10 SDK来获得Direct3D 11调试运行时。

对于Windows 10,您可以通过安装名为图形工具Windows可选功能来获得Direct3D调试运行时。对于Windows 10,这是特定于版本的,因此请确保您已启用它,以便它具有与您的版本相匹配的版本。查看此博客文章

参见Direct3D 11创建设备的解剖

最新更新