C#错误“尝试读取或写入受保护的内存"或“外部组件引发了异常" [英] C# error "Attempted to read or write protected memory" or "External component has thrown an exception"

查看:211
本文介绍了C#错误“尝试读取或写入受保护的内存"或“外部组件引发了异常"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个C#程序(目标框架.NET 4.0),该程序对COM对象(非托管代码)进行调用,对所有对象进行适当的管理,在不再需要时销毁,等等.

I have a C# program (target framework .NET 4.0) which makes calls to COM objects (unmanaged code), all objects managed properly, destroyed when no longer required, etc.

我也有很少的异常处理程序,可以尝试/捕获没有自定义异常的块.但是有时该程序崩溃了,在大多数情况下都可以正常工作,而且是随机行为.堆栈跟踪也有所不同,例如:

I have also few exceptions handler, try/catch blocks without custom exceptions. However some times this program crashed, works most of the times, random behaviour. Stack traces also vary, example:

System.AccessViolationException was unhandled
  Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
  Source=System.Windows.Forms
  StackTrace:
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at IndexerTester.Program.Main() in D:\Tester\Program.cs:line 17
  InnerException:

在Program.cs的第17行:Application.Run(new Form1());

In Program.cs, Line 17: Application.Run(new Form1());

System.Runtime.InteropServices.SEHException was unhandled
  Message=External component has thrown an exception.
  Source=System.Windows.Forms
  ErrorCode=-2147467259
  StackTrace:
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at IndexerTester.Program.Main() in D:\Tester\Program.cs:line 17
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException:

我正处于隔离阶段,以找出此错误的根源.

I am in isolation stage to find out root of this error.

  • 您对此错误有何建议?
  • 有关捕获这些异常并正常退出的任何建议.

感谢您的帮助.

推荐答案

异常的来源是未处理的代码,很可能是您的COM组件.堆栈跟踪表明异常被捕获在消息循环中,这可能是由于从.NET代码向STA(单线程单元)中的COM对象进行跨单元调用而导致的.然后将方法调用编组起来,并使用Windows消息将其发送到组件.

The source of the exceptions are unamanged code and most likely your COM components. The stack trace indicates that the exceptions are caught in your message loop and this might be a result of doing cross apartment calls from your .NET code into a COM object in a STA (Single Threaded Apartment). Method calls are then marshaled and sent using windows messages to the component.

进行跨单元调用没有错,但是当看到来自不同单元的指针并且通常对COM中的线程规则一无所知时,我看到一些COM组件没有进行正确的封送处理.如果您的应用程序中存在任何类型的多线程,那么您绝对应该研究一下.从主STA线程调用时,这些断开"的COM对象将表现良好,但在不同线程上调用或创建这些COM对象时,它们可能会失败.

There is nothing wrong about doing cross apartment calls, but I have seen some COM components not doing proper marshaling when given pointers from a different apartment and in general being ignorant about the threading rules in COM. If there is any kind of multi-threading in you application you should definitely look into this. These "broken" COM objects will behave well when called from the main STA thread but may fail when called or created on different threads.

更具体地说:假设您的应用程序UI线程在启动时进入STA(单线程单元)并创建COM组件.然后,您创建一个新线程(将在另一个单元中),并从该线程中调用COM组件上的方法.这是一个交叉公寓电话.您的COM组件只能在UI线程(它所驻留的单元的线程)上执行.COM框架会注意到您正在执行跨单元调用,它将调用序列化到缓冲区中(在COM lingo中为 marshal 调用).然后使用Windows消息将此缓冲区发送到UI线程.如果您的应用程序没有窗口,COM将创建一个隐藏的窗口来接收这些消息.然后,您的应用程序的消息循环将解压缩编组的调用并在UI线程上执行.

To be more specific: Lets say that your applications UI thread on startup enters a STA (Single Threaded Apartment) and creates the COM component. You then create a new thread (which will be in another apartment) and from this thread you call a method on the COM component. This is a cross apartment call. Your COM component can only execute on the UI thread (the thread of the apartment it lives in). The COM framework will note that you are doing a cross apartment call and it will serialize the call into a buffer (marshal the call in COM lingo). This buffer is then sent to the UI thread using a Windows message. If your application doesn't have a window COM will create a hidden window to receive these messages. The message loop of your application will then unpack the marshalled call and execute it on the UI thread.

现在,假设您或COM组件不了解COM公寓和编组规则.方法调用中的参数之一是指针或解析为指针的东西,并且该指针在COM组件的单元中无效.然后,当COM组件取消引用指针时,您将得到一个错误..NET运行时将检测到此情况,并抛出您看到的两种异常类型之一.但是,此异常在UI线程的消息循环中引发,您无法访问某些代码.在调用者处使用try-catch块无助于捕获异常,因为它是在另一个线程上引发的.无论如何,您不应该捕获该异常,因为它表明您的应用程序中发生了一些非常糟糕的事情.

Now, lets assume that either you or the COM component doesn't understand the rules of COM apartments and marshalling. One of the arguments in the method call is a pointer or something that resolves into a pointer and this pointer isn't valid in the apartment of the COM component. Then, when the COM component derefences the pointer you get an error. The .NET runtime will detect this and throw one of the two exception types you see. However, this exception is thrown in the message loop of the UI thread, some code you don't have access to. Using a try-catch block at the caller doesn't help catching the exception as it is thrown on another thread. Anyway, you shouldn't catch the exception because it is a sign of something really bad going on in your application.

记录下来,错误代码-2147467259是0x8004005,它转换为E_FAIL.并不是很有帮助,但是您遇到的错误很可能是由于COM组件中使用了无效的指针造成的.

For the record the error code -2147467259 is 0x8004005 which translates to E_FAIL. Not very helpful, but the errors you experience are most likely due to invalid pointers being used in the COM component.

要解决此问题,您将必须正确使用COM组件和/或修复组件中的任何损坏的代码.

To fix this you will have to use the COM components correctly and/or fix any broken code in the components.

这篇关于C#错误“尝试读取或写入受保护的内存"或“外部组件引发了异常"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆