我是一名新的C#程序员,并创建了一个应用程序,该应用程序使用第三方COM对象来跟踪来自呼叫记录服务器的电话呼叫记录。 COM软件的创建者也是制作呼叫录制软件的供应商,因此您认为它应该有效。我和他们的工作人员进行了很多电话和代码审查,他们提供的帮助很少。
应用程序响应来自COM对象的事件,如OnCallStart和OnCallEnd,AgentLogon,AgentLogoff,ServerDown等。我只是监视事件返回的内容并将其写入文件。应用程序编译没有问题,并运行几分钟,然后它给我以下错误(我不得不打开调试>例外菜单中的异常终于看到它):
检测到ReportAvOnComRelease 消息:捕获异常但在通过Marshal.Release或Marshal.ReleaseComObject释放COM接口指针时或在相应的RuntimeCallableWrapper被垃圾收集后隐式处理。这是用户引用计数错误或COM对象发布的其他问题的结果。确保正确管理refcounts。 COM接口指针的原始vtable指针是0x45ecbac。虽然这些类型的异常被CLR捕获,但它们仍然可能导致损坏和数据丢失,因此如果可能的话,应该解决导致异常的问题。
它给了我最多的东西。没有vtable细节,refcounts或其他任何东西。我编写了一个GC.Collect()并让应用程序运行一分钟然后解雇GC.Collect并得到错误。我可以用一些一致性做到这一点。我已经阅读了关于这个错误的文章和正确的Marshal的需要,但我不是那个编组。 VS为COM对象创建一个RCW,我使用它,所以我无法控制,或者我?这些文章都没有给我任何代码示例或除理论聊天之外的任何其他内容。
有更好的方法吗?如何准确找到导致错误的原因?似乎没有办法隔离这个东西。我发现微软的一篇文章称这是“沉默的刺客”,但他没有给出解决方案,并且基本上承认MS也没有。 Read Here
我在我的智慧结束。任何帮助表示赞赏。
答案 0 :(得分:1)
嗯,这是您正在使用的COM服务器中的严重缺陷。是的,它由CLR间接触发,当终结器线程运行RCW终结器时,释放COM对象的最后一个引用计数。 Marshal.ReleaseComObject将引用计数减少到0,COM服务器的IUnknown :: Release()实现方法将清理对象。
对于COM服务器来说,这总是很容易受到攻击。当它早先损坏堆时,触发CPU硬件故障(AV =访问冲突)的常见时间是它释放内存的时间。微软为此硬件异常提供了一个捕获程序,以帮助诊断问题。没有它,你几乎没有机会弄清楚发生了什么,因为终结器在一个不可预测的时间运行,而你的代码没有任何主动运行。
故障是非常严重的,你留下了一个只被部分清理的损坏的堆。如果你继续前进,你通常会得到更多的AV和/或你会泄漏内存。最糟糕的结果,很可能是btw,它不会在之后死亡,但只是开始产生不良数据或行为不当,导致你认为你的代码是错误的。
只有一方可以解决此问题,即此COM服务器的供应商。仔细指定您运行的计算机,尤其是操作系统版本很重要,并为它们提供一小段代码(包括源代码),以重现异常。保持它小而高度可见是重要的,或者他们会声称这是你的代码破坏了堆。无论如何,它们很可能会这样做,堆损坏非常难以调试。如果你无法让他们做出回应,那么购买其他供应商是明智的。