SharpDX创建SwapChain1触发AccessViolationException问题排查
问题描述
尝试在SharpDX中创建SwapChain1,实现代码如下:
SwapChainDescription1 desc = new() { Width = toSetSize.Value.Width, Height = toSetSize.Value.Height, Format = Format.R8G8B8A8_UNorm, Stereo = false, SampleDescription = new SampleDescription(1, 0), Usage = Usage.BackBuffer | Usage.RenderTargetOutput, BufferCount = 1, Scaling = Scaling.Stretch, SwapEffect = SwapEffect.Discard }; SwapChainFullScreenDescription scd = new SwapChainFullScreenDescription() { RefreshRate = new Rational(60, 1), Scaling = DisplayModeScaling.Stretched, Windowed = false }; using (var dxgiDevice2 = device.QueryInterface<SharpDX.DXGI.Device2>()) using (var dxgiAdapter = dxgiDevice2.Adapter) using (var dxgiFactory2 = dxgiAdapter.GetParent<SharpDX.DXGI.Factory2>()) { res = new SwapChain1(dxgiAdapter.GetParent<SharpDX.DXGI.Factory2>(), device, Window.Handle, ref desc, scd); return res; }
运行时触发AccessViolationException,提示“Attempted to read or write corrupted memory”。调整desc和scd参数无效,排查发现factory.NativePointer曾为IntPtr.Zero并更新代码,开启原生调试后得到报错:
Exception called at 0x759CE292 in Demo.exe: Microsoft C++ Exception: _com_error at location 0x0297C5B8. Exception called at 0x6BA81D22 (dxgi.dll) in Demo.exe: 0xC0000005: Access violation at position 0x000000B8.
德语原文:
Ausnahme ausgelöst bei 0x759CE292 in Demo.exe: Microsoft C++-Ausnahme: _com_error bei Speicherort 0x0297C5B8. Ausnahme ausgelöst bei 0x6BA81D22 (dxgi.dll) in Demo.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x000000B8.
问题根源与修复方法
1. 核心问题:重复获取Factory2导致的COM对象生命周期异常
代码中已在using块内获取了dxgiFactory2实例,但创建SwapChain1时又调用dxgiAdapter.GetParent<SharpDX.DXGI.Factory2>()重新获取Factory实例。这种重复获取会导致新实例未被SharpDX的托管机制正确管理,其内部COM对象可能提前释放,进而引发内存访问错误。
2. 修复代码
直接使用using块内已创建的dxgiFactory2实例,避免重复获取:
SwapChainDescription1 desc = new() { Width = toSetSize.Value.Width, Height = toSetSize.Value.Height, Format = Format.R8G8B8A8_UNorm, Stereo = false, SampleDescription = new SampleDescription(1, 0), Usage = Usage.BackBuffer | Usage.RenderTargetOutput, BufferCount = 1, Scaling = Scaling.Stretch, SwapEffect = SwapEffect.Discard }; SwapChainFullScreenDescription scd = new SwapChainFullScreenDescription() { RefreshRate = new Rational(60, 1), Scaling = DisplayModeScaling.Stretched, Windowed = false }; using (var dxgiDevice2 = device.QueryInterface<SharpDX.DXGI.Device2>()) using (var dxgiAdapter = dxgiDevice2.Adapter) using (var dxgiFactory2 = dxgiAdapter.GetParent<SharpDX.DXGI.Factory2>()) { // 使用已托管的dxgiFactory2实例 res = new SwapChain1(dxgiFactory2, device, Window.Handle, ref desc, scd); return res; }
3. 额外验证点
- 确认
device是有效的D3D设备实例,且版本支持DXGI Device2接口 - 检查
Window.Handle为有效窗口句柄,窗口已完成初始化 - 若仍报错,尝试将
SwapEffect改为SwapEffect.FlipSequential,部分硬件对Discard模式兼容性有限
内容的提问来源于stack exchange,提问作者user19815545
相关产品推荐
相关产品推荐

