注释
本文特定于 .NET Framework。 它不适用于 .NET 的较新版本实现,包括 .NET 6 及更高版本。
invalidCERCall当在受约束的执行区域(CER)图中调用没有可靠性协定或过度弱协定的方法时,将激活托管调试助手(MDA)。 弱协定是一个协定,它声明最坏的情况状态损坏的范围大于传递给调用的实例的范围,即, AppDomain 或进程状态可能会损坏,或者当在 CER 中调用时,其结果并不总是具有确定性的可争辩性。
症状
在 CER 中执行代码时出现意外结果。 症状并不具体。 在调用不可靠的方法时,它们可能是一个意外 OutOfMemoryException的、异常 ThreadAbortException或其他异常,因为运行时未提前对其进行准备或防止 ThreadAbortException 运行时出现异常。 更大的威胁是,运行时方法导致的任何异常都可能使或进程处于 AppDomain 不稳定状态,这与 CER 的目标相反。 CER 创建的原因是避免状态损坏,例如这种情况。 损坏状态的症状特定于应用程序,因为应用程序之间的一致状态的定义不同。
原因
CER 中的代码调用一个不 ReliabilityContractAttribute 与 CER 中运行不兼容的函数 ReliabilityContractAttribute 或弱函数。
在可靠性协定语法方面,弱协定是一个不指定Consistency枚举值或指定Consistency值或MayCorruptAppDomainNone指定值的MayCorruptProcess协定。 上述任何条件都表明调用的代码可能会妨碍 CER 中的其他代码保持一致状态的努力。 CER 允许代码以非常确定的方式处理错误,维护对应用程序非常重要的内部固定,并允许它面对暂时性错误(如内存不足异常)继续运行。
激活此 MDA 表示 CER 中调用的方法可能失败,其方式可能是调用方没有期望或使 AppDomain 或进程状态损坏或不可恢复。 当然,调用的代码可能正确执行,问题只是缺少协定。 但是,编写可靠代码所涉及的问题很微妙,并且缺少协定是代码可能无法正确执行的良好指标。 合同是程序员可靠编码的指标,还承诺这些保证在将来的代码修订中不会更改。 也就是说,协定是意向声明,而不仅仅是实现细节。
由于任何具有弱或不存在协定的方法都可能以许多不可预知的方式失败,因此运行时不会尝试从延迟 JIT 编译、泛型字典填充或线程中止引入的方法中删除其任何不可预知的失败。 也就是说,当激活此 MDA 时,它指示运行时未在定义的 CER 中包含调用的方法;调用图在此节点上终止,因为继续准备此子树有助于屏蔽潜在的错误。
决议
向函数添加有效的可靠性协定,或避免使用该函数调用。
对运行时的影响
从 CER 调用弱协定的效果可能是 CER 未能完成其作。 这可能会导致进程状态损坏 AppDomain 。
输出
下面是此 MDA 的示例输出。
Method 'MethodWithCer', while executing within a constrained execution region, makes a call at IL offset 0x000C to 'MethodWithWeakContract', which does not have a sufficiently strong reliability contract and might cause non-deterministic results.
配置
<mdaConfig>
<assistants>
<invalidCERCall />
</assistants>
</mdaConfig>