首页 > 解决方案 > 将操作放入 lambda 会导致 C# 中的 SystemAccessViolation

问题描述

我很困惑为什么SystemAccessViolation当我取消注释调用该操作的行时会出现以下代码。

GL.Enable(EnableCap.DebugOutput);
GL.Enable(EnableCap.DebugOutputSynchronous);

Action action = () => { Console.WriteLine("Hello"); };

DebugProc debugProc = (source, type, id, severity, length, message, userParam) =>
{
    string msg = Marshal.PtrToStringAnsi(message, length);
    Console.WriteLine("Debug message: " + msg);
    // Uncommenting this causes a SystemAccessViolation.
    //action.Invoke();
};

GL.DebugMessageCallback(debugProc, IntPtr.Zero);

当我在非调试模式下运行它时,我得到:

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
    at OpenTK.Graphics.OpenGL4.GL.BufferData[T2](BufferTarget target, Int32 size, T2[] data, BufferUsageHint usage)

当我通过调试运行它时,我得到:

Unexpected exception: Object reference not set to an instance of an object.
Stack trace:
    at System.StubHelpers.StubHelpers.CheckCollectedDelegateMDA(IntPtr pEntryThunk)
    at OpenTK.Graphics.OpenGL4.GL.BufferData[T2](BufferTarget target, Int32 size, T2[] data, BufferUsageHint usage)

我也不确定我的问题是否应该报告给 OpenTK,或者我在 C# 中做错了什么(使用 C# 8、.NET Framework 4.8)。

只要在 lambda 内部调用的操作被注释掉,上面的代码就可以正常工作。

对于不熟悉 OpenGL 的任何人,GL.DebugMessageCallback()最有可能会做一些原生的东西。正因为如此,我不知道这是否意味着 C# 失去了对动作的跟踪并尝试做不应该做的事情,或者 OpenGL 正在做的事情与我编写的代码不匹配。GC是否有可能已经清理action并试图调用它?我猜在这一点上。

action()当未注释时,我无法在其中放置断点,断点不会被触发。action()但是,当完全注释掉时,我可以使断点工作。调用的顺序与它是在 lambda 的顶部还是底部无关。

标签: c#opentk

解决方案


推荐阅读