System.AccessViolationException 来自非托管代码?

Posted

技术标签:

【中文标题】System.AccessViolationException 来自非托管代码?【英文标题】:System.AccessViolationException from unmanaged code? 【发布时间】:2010-09-06 14:54:31 【问题描述】:

我正在编写这个库,它通过将由托管代码使用的媒体基础框架在 C++/CLI 中实现一些基本的音频播放器功能。我可以很好地播放音频、停止、暂停等。对于不熟悉 Media Foundation 的任何人,媒体会话都会发布您可以处理的事件以获取通知。这是通过使用 IMFAsyncCallback 对象在会话对象上调用 BeginGetEvent 来完成的。 IMFAsyncCallback 定义了您应实施以处理事件的方法 Invoke(IMFAsyncResult)。当事件发生时,工作线程上的会话对象会调用调用方法,该对象具有您可以查询事件信息的 IMFAsyncResult 对象。此结果对象由事件线程创建和拥有。

在我的 Invoke 实现中,每当我尝试使用传递的 IMFAsyncResult 对象执行任何操作(包括调用 QueryInterface 或其他操作)时,都会收到 System.AccessViolationException。我实现 IMFAsyncCallback 的对象是在 CRT 堆上分配的基本 C++ 类(非托管),事件发布在会话对象拥有的线程上,该线程也分配在 CRT 堆上。

    什么可能导致此异常?

    为什么我会从使用普通旧 C++ 实现的代码中抛出 .NET 托管异常?当你有一个混合模式程序集时会发生这种情况吗?

【问题讨论】:

【参考方案1】:

Capture a crash dump,然后将其加载到VS 2010或WinDbg中进行分析,一切都会显示出来。 VS 2010 会更简单,但 WinDbg 可能更有效。

由于使用 WinDbg 是更复杂的选项,我将详细说明(根据您的目标平台选择以下 32 位或 64 位版本):

下载安装Debugging Tools for Windows 为Microsoft Symbol Server 配置调试符号

.sympath srv*<SymbolCacheDir>*http://msdl.microsoft.com/download/symbols

将故障转储文件加载到 WinDbg(文件->打开故障转储...) 为您的模块配置调试符号

.sympath+ <PrivatePdbDir>

将 SOS 扩展加载到 WinDbg 中

.loadby sos mscorwks; * fw 2-3.5

.loadby sos clr; * fw 4

下载、提取和加载SOSEX 扩展到 WinDbg

.load <Sosex32or64Dir>\sosex

让 WinDbg 进行分析

!analyze -v

使用 SOSEX 显示当前线程堆栈(包括托管和非托管帧)

!mk

这很可能会回答您的问题。

【讨论】:

关于如何捕获故障转储的链接已失效。 @GrixM 已修复。 ;)【参考方案2】:

听起来您对此有一个简单的重现 - 您应该能够通过在程序运行时附加调试器并在发生访问冲突时捕获访问冲突来调试问题。通常,库会包装它并将其作为另一种类型呈现,并且异常的原始位置并不明显。

要从 Visual Studio 附加到您的进程,请参阅 here。附加到恶意进程时,请确保选择调试本机和托管代码的选项。尽可能确保您的程序集和 DLL 的符号在 Symbol path 中可用(如果它们是第三方代码,有些可能不可用)。

要更改异常配置,以便在源代码处调试访问冲突,请参阅here。

【讨论】:

以上是关于System.AccessViolationException 来自非托管代码?的主要内容,如果未能解决你的问题,请参考以下文章