在 clr 调用堆栈中看到接口是否正常

本文关键字:接口 是否 clr 调用 堆栈 | 更新日期: 2023-09-27 18:32:10

我有一个 asp.net 应用程序,它正在崩溃。在 Windows 事件日志中有一个包含此调用堆栈的条目:

 Exception type: EntryPointNotFoundException 
    Exception message: Entry point was not found.
   at ***.Interfaces.Portal.Repository.ILookup.get_LookupDataCollection()
   at ***.Portal.Repository.Lookup.GetLookUpValue(ILookup lookup, Int32 index)
   at ***.Portal.Repository.Lookup.GetLookUpValue(ILookup lookup)
   at ***.HttpModules.RuntimeHttpModule.SetPageUrlInfoInContext(PageUrlInfo pinfo)
   at ***PortalRuntime.HttpModules.RuntimeHttpModule.BeginRequest(Object sender, EventArgs e)
   at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

这仅在客户机器上发生,我无法在本地重现它。 正如你在顶部看到的,有一个接口(ILookup,它实际上是一个接口,而不是一个类)。

我构建了一个类似的示例(通过接口调用的方法)。Visual Studio 2015 足够聪明,可以显示这一点:

ConsoleApplication2.exe!ConsoleApplication2.Lookup.GetLookupId(ConsoleApplication2.ILookup lookup) Line 37  C#

但是在那里你仍然可以看到实现该方法的类。我还使用 windbg 附加到我的样本,并在应用程序位于通过接口调用的方法中的断点中时打印堆栈:接口不在堆栈上。

这是我的问题:

  • 在 clr 调用堆栈中看到接口是否正常(尤其是没有实现它的类)? 我想我以前从未见过这样的调用堆栈...别人?(我的意思是一般的,不管我问题的第二部分如何)

  • 这是一个非常相似的问题:@Hans Passant在他的第一条评论中说"未能解决接口方法的实现方法",OP说"你已经用你的第一条评论回答了我的问题"。那么这真的是根本原因吗?有谁知道这个问题的解决方法?还是只是一个特殊的 CLR 版本?

在 clr 调用堆栈中看到接口是否正常

我可以解释为什么你会看到这一点,这对解决你的问题根本没有帮助。 我对 CLR 将接口方法绑定到其实现的方式也不够了解,它是疯狂的微优化。

问题是抖动必须为包含接口方法调用的方法生成代码。 但它还不能知道对象引用的标识。 在代码实际执行之前,这还不知道 100% 准确。 因此,它所做的是为目标方法分配一个存根,一个占位符。 并为该存根生成 CALL 指令。 该存根方法的实际名称无关紧要,当解析真正的目标方法时,它将再次消失。

存根本身生成对 CLR 的调用以解析目标方法,现在知道对象引用的真实标识,从而知道需要执行哪个特定的实现方法。 并修补机器代码,以便替换 CALL 地址。 因此,下次执行该方法时,您无需支付方法绑定的代价,并且调用以最大可能的曲速运行。

如前所述,存根的名称无关紧要,因为它是临时的。 为其指定接口方法的名称对于诊断 MissingMethodException 非常有帮助。 好主意。

真正的问题是加载的程序集

不是您用来构建代码的程序集。 可能是您忘记重新部署的旧版本。 或者,当您更改界面时,您只是忘记重建它,因为它不是解决方案的一部分。 因此,它没有接口方法的实现,CLR 在存根执行时很晚才发现这一点。 因此,您会在调用堆栈上看到存根方法名称。