使用 3rd 方 COM 时出现 ReportAvOnComRelease 异常
我是一名新的 C# 程序员,创建了一个应用程序,该应用程序使用第 3 方 COM 对象来跟踪来自通话录音服务器的电话通话录音。 COM 软件的创建者也是制造通话录音软件的供应商,因此您会认为它应该可以工作。我与他们的员工打了很多电话并进行了代码审查,但他们几乎没有提供任何帮助。
应用程序响应来自 COM 对象的事件,例如 OnCallStart 和 OnCallEnd、AgentLogon、AgentLogoff、ServerDown 等。我所做的只是监视事件返回的内容并将其写入文件。该应用程序编译没有问题并运行了几分钟,然后出现以下错误(我必须在“调试”>“异常”菜单中打开“异常”才能最终看到它):
检测到 ReportAvOnComRelease
消息:在通过 Marshal.Release 或 Marshal.ReleaseComObject 释放 COM 接口指针时或在垃圾收集相应的 RuntimeCallableWrapper 之后隐式释放 COM 接口指针时,捕获了异常,但进行了处理。这是由于用户引用计数错误或 COM 对象的 Release 的其他问题造成的。确保正确管理重新计票。 COM接口指针的原始vtable指针是0x45ecbac。虽然这些类型的异常被 CLR 捕获,但它们仍然可能导致损坏和数据丢失,因此如果可能,应解决导致异常的问题。
它给我的仅此而已。没有 vtable 详细信息、引用计数或其他任何内容。我编写了 GC.Collect() 并让应用程序运行一分钟,然后触发 GC.Collect 并收到错误。我可以保持一定的一致性。我已经阅读了一篇又一篇关于此错误以及正确编组的必要性的文章,但我不是负责编组的人。 VS 为 COM 对象创建了一个 RCW,我使用它,所以我无法控制那里,或者是吗?这些文章都没有给我提供任何代码示例或除了理论闲聊之外的任何内容。
有更好的方法吗?我怎样才能准确地找到导致错误的原因?似乎没有办法隔离这个东西。我找到了一篇来自微软的文章,称其为“沉默的刺客”,但他没有给出解决方案,并且基本上承认微软也没有任何解决方案。 阅读此处
我束手无策。任何帮助表示赞赏。
I am a new C# programmer and have created an application which uses a 3rd party COM object to track telephone call recordings from a call recording server. The creator of the COM software is also the vendor who makes the call recording software, so you would think it should work. I have been on many phone calls and code reviews with their staff and they have come up with very little to help.
The application responds to events from the COM object like OnCallStart and OnCallEnd, AgentLogon, AgentLogoff, ServerDown, etc. I do nothing more than monitor what the events return and write it to a file. The application compiles without a problem and runs for a few minutes and then it gives me the following error (I had to open up the Exception in the Debug>Exceptions menu to finally see it):
ReportAvOnComRelease was detected
Message: An exception was caught but handled while releasing a COM interface pointer through Marshal.Release or Marshal.ReleaseComObject or implicitly after the corresponding RuntimeCallableWrapper was garbage collected. This is the result of a user refcount error or other problem with a COM object's Release. Make sure refcounts are managed properly. The COM interface pointer's original vtable pointer was 0x45ecbac. While these types of exceptions are caught by the CLR, they can still lead to corruption and data loss so if possible the issue causing the exception should be addressed.
It gives me no more than that. No vtable details, refcounts or anything else. I coded a GC.Collect() and let the app run for a minute and then fired the GC.Collect and got the error. I can do that with some consistency. I have read article after article about this error and the need to Marshal correctly, but I am not the one marshaling. VS creates a RCW for the COM object and I use that so I have no control there, or do I? None of the articles gave me any code examples or anything other than theoretical chit chat.
Is there a better way to do this? How can I find exactly what is causing the error? There seems to be no way to isolate this thing. I found one article from a guy from Microsoft that called this the "Silent Assassin", but he gave no solutions and essentially admitted that MS didn't have any either. Read Here
I am at my wits end. Any help is appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
嗯,这是您正在使用的 COM 服务器的一个严重缺陷。是的,它是由CLR间接触发的,当终结器线程运行RCW终结器时,COM对象的最后一个引用计数被释放。 Marshal.ReleaseComObject 将引用计数减至 0,COM 服务器的 IUnknown::Release() 实现方法将清理该对象。
对于 COM 服务器来说,这始终是一个容易受到攻击的时期。当它之前损坏堆时,触发 CPU 硬件故障(AV = 访问冲突)的常见时间是释放内存时。 Microsoft 为此硬件异常设置了捕获器以帮助诊断问题。如果没有它,您几乎没有机会弄清楚发生了什么,因为终结器在不可预测的时间运行,而您自己的任何代码都没有主动运行。
错误非常严重,您留下了一个仅部分清理的损坏堆。如果你继续这样做,你通常只会得到更多的反病毒和/或你会泄漏内存。顺便说一句,最糟糕的可能结果很可能是它之后不会死掉,而是开始生成不良数据或行为不可预测,导致您认为是您的代码有问题。
只有一方可以解决此问题,即该 COM 服务器的供应商。仔细指定您正在运行的机器,尤其是操作系统版本很重要,并给他们一小段重现异常的代码(包括源代码)。保持它小且高度可见很重要,否则他们会声称是您的代码损坏了堆。无论如何,他们很可能会这样做,堆损坏非常难以调试。如果您无法让他们做出回应,您最好选择其他供应商。
Well, it is a serious defect in the COM server you are using. Yes, it is indirectly triggered by the CLR, the last reference count of a COM object is released when the finalizer thread runs the RCW finalizer. Marshal.ReleaseComObject counts the reference count down to 0 and the COM server's IUnknown::Release() implementation method will clean up the object.
That's always a vulnerable time for a COM server. When it corrupted the heap earlier, a common time for this to trigger a CPU hardware fault (AV = Access Violation) is when it releases memory. Microsoft put a catcher for this hardware exception in place to help diagnose the problem. Without it, you'd have very little chance to figure out what happened because the finalizer runs at an unpredictable time without any of your own code actively running.
The fault is quite serious, you're left with a corrupted heap that's only partly cleaned up. If you keep going, you'll typically just get more AVs and/or you'll leak memory. The worst possible outcome, quite likely btw, is that it doesn't die afterwards but just starts generating bad data or misbehaves unpredictable, causing you to think that it is your code that is buggy.
There's only one party that can fix this problem, the supplier of this COM server. Carefully specify the machine you are running on, especially the operating system version is important, and give them a small piece of code (source included) that reproduces the exception. Keeping it small and highly visible is important or they'll claim it was your code that corrupted the heap. They are likely to do so anyway, heap corruption is very difficult to debug. If you cannot get them responsive, you'd be wise to shop for another vendor.