CodeContracts - 误报
我刚刚开始在现有的中型项目上尝试 .NET 4 中的 CodeContracts,令我惊讶的是静态检查器向我发出有关以下代码片段的编译时警告:
public class Foo
{
private readonly List<string> strs = new List<string>();
public void DoSomething()
{
// Compiler warning from the static checker:
// "requires unproven: source != null"
strs.Add("hello");
}
}
Why is the CodeContracts static checker 抱怨关于 strs.Add(...) 行? strs 不可能为空,对吧?我做错了什么吗?
I've just started experimenting with CodeContracts in .NET 4 on an existing medium-sized project, and I'm surprised that the static checker is giving me compile-time warnings about the following piece of code:
public class Foo
{
private readonly List<string> strs = new List<string>();
public void DoSomething()
{
// Compiler warning from the static checker:
// "requires unproven: source != null"
strs.Add("hello");
}
}
Why is the CodeContracts static checker complaining about the strs.Add(...) line? There's no possible way for strs to be null, right? Am I doing something wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
该字段可能被标记为只读,但不幸的是静态检查器对此不够智能。因此,由于静态检查器无法自行推断
strs
永远不会为 null,因此您必须通过不变量显式地告诉它:The field may be marked
readonly
, but unfortunately the static checker isn't smart enough for this. Therefore, as the static checker isn't able to infer on its own thatstrs
is never null, you must explicitly tell it through an invariant:以下是有效的代码,我希望它会生成警告。
他们的分析器很可能无法确保构造函数中没有任何内容会更改
strs
的值。或者也许您正在以某种方式更改构造函数中的strs
而您没有意识到。The following is valid code, which I would expect to generate the warning.
It's quite possible that their analyzer doesn't go so far as to make sure that you have nothing in a constructor that changes the value of
strs
. Or maybe you are somehow changingstrs
in a constructor and you don't realize it.小修正:Pex 使用 Z3(一种 SMT 求解器),而 Clousot(静态检查器代码名称)使用抽象解释和抽象域。
Little correction: Pex uses Z3, an SMT solver while Clousot (the static checker code name) uses abstract interpretation and abstract domains.
我对 .NET 对象初始化语义的复杂性了解不够,无法回答您的直接问题。不过,这里有两个提示:
Contract.Assume
来帮助它(或者,如果您有信心,可以使用Contract.Assert
)。有趣的是,如果您显式添加对象不变断言,即
strs
永远不会为null
,CC 能够证明这一点 因此,还可以证明strs.Add()
永远不会是空引用:所以,我想我的预感 #2 是正确的:CC 在这种情况下只是完全错误的。 (或者更准确地说:C# 语义到定理证明者中的编码是不完整的。)
I'm not knowledgeable enough with the intricacies of .NET's object initialization semantics to answer your direct question. However, here's two tips:
null
, doesn't mean it isn't true. IOW: CC might just be wrong and you need to help it along with aContract.Assume
(or, if you're feeling confident,Contract.Assert
).Interestingly, if you explicitly add the Object Invariant Assertion that
strs
can never benull
, CC is able to prove that and, consequently, can also prove thatstrs.Add()
will never be a null reference:So, I guess my hunch #2 is correct: CC is just simply wrong in this case. (Or more precisely: the encoding of the semantics of C# into the theorem prover is incomplete.)