VS2022 C++ DirectX模板添加着色器CreateVertexShader报错VSb无效
VS2022 基础C++ DirectX项目添加着色器触发内存访问错误
问题表现
在VS2022自带的C++ DirectX项目模板基础上手动添加着色器加载逻辑后,程序运行中断在CreateVertexShader调用行,调试显示VSb变量值为0xFFFFFFFFFFFFFFFF,触发内存访问错误。
项目默认生成的BasicAppasdMain构造函数原始代码
BasicAppasdMain::BasicAppasdMain(const std::shared_ptr<DX::DeviceResources>& deviceResources) : m_deviceResources(deviceResources) { m_deviceResources->RegisterDeviceNotify(this); m_sceneRenderer = std::unique_ptr<Sample3DSceneRenderer>(new Sample3DSceneRenderer(m_deviceResources)); m_fpsTextRenderer = std::unique_ptr<SampleFpsTextRenderer>(new SampleFpsTextRenderer(m_deviceResources)); }
出错的修改后代码
BasicAppasdMain::BasicAppasdMain(const std::shared_ptr<DX::DeviceResources>& deviceResources) : m_deviceResources(deviceResources) { // 注册设备丢失/重建通知 m_deviceResources->RegisterDeviceNotify(this); m_sceneRenderer = std::unique_ptr<Sample3DSceneRenderer>(new Sample3DSceneRenderer(m_deviceResources)); m_fpsTextRenderer = std::unique_ptr<SampleFpsTextRenderer>(new SampleFpsTextRenderer(m_deviceResources)); ID3D11VertexShader *VS; ID3DBlob* VSb; D3DReadFileToBlob(L"..//x64//Debug//BasicAppasd//VertexShader1.cso",&VSb); ID3D11Device* pDx11Device = deviceResources->GetD3DDevice(); pDx11Device->CreateVertexShader(VSb->GetBufferPointer(), VSb->GetBufferSize(), NULL, &VS); }
错误原因
- 核心问题是
D3DReadFileToBlob调用失败,没有成功加载着色器编译后的cso文件,VSb是未初始化的野指针,并非有效的ID3DBlob实例,后续调用VSb->GetBufferPointer()直接访问非法内存触发崩溃。 - 路径写法错误:VS运行DirectX模板程序时默认工作目录为项目根目录,硬编码的相对路径
..//x64//Debug//BasicAppasd//VertexShader1.cso无法定位到cso文件,同时正斜杠作为路径分隔符不需要写双斜杠。 - 没有对D3D API的返回值做校验,默认所有调用都成功,是DirectX开发的常见低级错误。
修复方案
- 先配置HLSL文件的编译属性:右键项目中的
VertexShader1.hlsl文件打开属性页,将项类型设置为HLSL编译器,着色器类型选择「顶点着色器(/VS)」,着色器模型选择适配项目的版本(一般选vs_5_0即可),输出文件设置为$(OutDir)%(Filename).cso,确保编译项目时cso文件会生成到程序输出目录。 - 修正文件路径,添加API返回值校验,修复后的代码如下:
BasicAppasdMain::BasicAppasdMain(const std::shared_ptr<DX::DeviceResources>& deviceResources) : m_deviceResources(deviceResources) { m_deviceResources->RegisterDeviceNotify(this); m_sceneRenderer = std::unique_ptr<Sample3DSceneRenderer>(new Sample3DSceneRenderer(m_deviceResources)); m_fpsTextRenderer = std::unique_ptr<SampleFpsTextRenderer>(new SampleFpsTextRenderer(m_deviceResources)); ID3D11VertexShader *VS = nullptr; ID3DBlob* VSb = nullptr; // 直接从输出目录读取cso,不要硬编码平台和配置路径 HRESULT hr = D3DReadFileToBlob(L"VertexShader1.cso", &VSb); // 校验读取结果,失败直接终止流程,不要继续执行 if (FAILED(hr)) { throw std::runtime_error("Failed to load vertex shader cso, please check file path and hlsl compile config"); } ID3D11Device* pDx11Device = deviceResources->GetD3DDevice(); hr = pDx11Device->CreateVertexShader(VSb->GetBufferPointer(), VSb->GetBufferSize(), nullptr, &VS); if (FAILED(hr)) { VSb->Release(); throw std::runtime_error("Failed to create vertex shader"); } // 后续使用完VS和VSb记得调用Release()释放,推荐用Microsoft::WRL::ComPtr管理COM对象自动释放,避免内存泄漏 }
调试提示:如果仍然提示找不到文件,可以在调用
D3DReadFileToBlob前调用GetCurrentDirectory打印当前工作目录,对照调整cso文件存放路径即可。
内容的提问来源于stack exchange,提问作者user11689090
相关产品推荐
相关产品推荐

