来自非托管代码的 System.AccessViolationException?
我正在编写这个库,它通过将由托管代码使用的媒体基础框架在 C++/CLI 中实现一些基本的音频播放器功能。我可以很好地播放音频、停止、暂停等。对于任何不熟悉 Media Foundation 的人,媒体会话都会发布您可以处理通知的事件。这是通过使用 IMFAsyncCallback 对象在会话对象上调用 BeginGetEvent 来完成的。 IMFAsyncCallback 定义了您应该实现来处理事件的方法 Invoke(IMFAsyncResult)。当事件发生时,工作线程上的会话对象将调用 invoke 方法,并使用可查询事件信息的 IMFAsyncResult 对象。该结果对象由事件线程创建并拥有。
在我的 Invoke 实现中,每当我尝试使用传递的 IMFAsyncResult 对象执行任何操作(包括仅调用 QueryInterface 或其他操作)时,都会收到 System.AccessViolationException。我实现 IMFAsyncCallback 的对象是分配在 CRT 堆上的基本 C++ 类(非托管),事件发布在同样分配在 CRT 堆上的会话对象拥有的线程上。
什么可能导致此异常?
为什么我会从用普通旧式 C++ 实现的代码中抛出 .NET 托管异常?这就是当您使用混合模式程序集时会发生的情况吗?
I'm writing this library that implements some basic audio player features in C++/CLI via the Media Foundation framework that will be consumed by managed code. I can play audio, stop, pause, etc just fine. For anyone who is not familiar with Media Foundation, the media session posts events that you can handle for notifications. This is done by calling BeginGetEvent on the session object with an IMFAsyncCallback object. The IMFAsyncCallback defines the method Invoke(IMFAsyncResult) that you should implement to handle the events. When an event occurs, the invoke method is called by the session object on a work thread with an IMFAsyncResult object that you can query for the event info. This result object is created and owned by the event thread.
In my implementation of Invoke, whenever I try and do anything (that includes just calling QueryInterface or something) with the IMFAsyncResult object that I am passed, I get a System.AccessViolationException. The object I have implementing IMFAsyncCallback is a basic C++ class (not managed) allocated on the CRT heap and the events are posted on a thread owned by the session object also allocated on the CRT heap.
What could be causing this exception?
Why am I getting a .NET managed exception thrown from code that is implemented in plain old C++? Is that just what happens when you have a mixed mode assembly?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
捕获故障转储,然后加载到VS 2010或者WinDbg中进行分析,一切就都显现出来了。 VS 2010 会更容易,但 WinDbg 可能更有效。
由于使用 WinDbg 是更复杂的选项,我将对此进行详细说明(根据您的目标平台选择以下版本的 32 位或 64 位版本):
.sympath srv**http://msdl.microsoft.com/download/symbols< /code>
.sympath+
.loadby sos mscorwks; * fw 2-3.5
或
.loadby sos clr; * fw 4
中。 load\sosex
!analyze -v
!mk
代码>这很可能会回答您的问题。
Capture a crash dump, then load it into VS 2010 or WinDbg for analysis, and all shall be revealed. VS 2010 will be easier, but WinDbg might be more effective.
Since using WinDbg is the more complicated option I'll elaborate on that (choose the 32-bit or 64-bit versions of the following according to your target platform):
.sympath srv*<SymbolCacheDir>*http://msdl.microsoft.com/download/symbols
.sympath+ <PrivatePdbDir>
.loadby sos mscorwks; * fw 2-3.5
or
.loadby sos clr; * fw 4
.load <Sosex32or64Dir>\sosex
!analyze -v
!mk
This will most likely answer your questions.
听起来您可以轻松重现这一点 - 您应该能够通过在程序运行时附加调试器并在发生访问冲突时捕获该问题来调试问题。通常,库会包装它并将其显示为另一种类型,并且异常的原始站点并不明显。
要从 Visual Studio 附加到您的流程,请参阅此处。当您附加到恶意进程时,请确保选择调试本机代码和托管代码的选项。确保程序集和 DLL 的符号在 符号路径,尽可能多(有些如果是第三方代码可能不可用)。
要更改异常配置以便在源代码处调试访问冲突,请参阅 这里。
Sounds like you have an easy repro of this - you should be able to debug the problem by attaching the debugger while the program is running and enabling Access Violation to be trapped at the point at which it occurs. Often, libraries wrap this and surface it as another type, and the original site of the exception is not apparent.
To attach to your process from Visual Studio see here. When you attach to your rogue process, make sure you select the options to debug native and managed code. Make sure symbols for your assemblies and DLLs are available in the Symbol path,as far as you can (some may not be available if they are third-party code).
To alter Exception config so that access violation is debuggable at source, see here.