草庐IT

c# - C#代码契约(Contract): What can be statically proven and what can't?

coder 2023-07-12 原文

我可能会说我对代码契约(Contract)非常熟悉:我已经阅读并理解了大多数user manual,并且已经使用了一段时间了,但是我仍然有疑问。当我在SO中搜索“未经验证的代码契约(Contract)”时,有很多命中之处,都在问为什么不能静态证明其特定声明。尽管我可以做同样的事情并发布我的特定场景(顺便说一句:

),



我宁愿理解为什么任何代码契约(Contract)条件都可以被证明或无法被证明。有时我对它可以证明的事情印象深刻,有时我……很好……客气地说:绝对没有留下深刻的印象。如果我想了解这一点,我想知道静态检查器使用的机制。我敢肯定,我会从经验中学习,但是我到处喷洒Contract.Assume语句以消除警告,我觉得那不是代码契约(Contract)的目的。谷歌搜索并没有帮助我,所以我想问你们的经验:您看到了哪些(显而易见的)模式?是什么让您看到了光?

最佳答案

您的施工契约(Contract)不满意。由于您正在引用对象的字段(this.data),因此其他线程可能会访问该字段,并且可能会在“假定”和第一个参数分辨率与第三个参数分辨率之间更改其值。 (即,它们可以是三个完全不同的数组。)

您应该将数组分配给局部变量,然后在整个方法中使用该变量。然后,分析器将知道约束已得到满足,因为没有其他线程能够更改引用。

var localData = this.data;
if (localData == null) return;
byte[] newData = new byte[localData.Length]; // Or whatever the datatype is.
Array.Copy(localData, newData, localData.Length); // Now, this cannot fail.

这不仅带来了满足约束的好处,而且实际上使代码在许多情况下更加健壮。

我希望这能引导您找到问题的答案。我实际上无法直接回答您的问题,因为我无权访问包含静态检查器的Visual Studio版本。 (我使用的是VS2008 Pro。)我的回答基于我对代码的视觉检查得出的结论,并且看来静态契约(Contract)检查器使用了类似的技术。我很生气!我需要让我一个。 :-D

更新:(有很多猜测)

经过反射(reflection),我想我可以很好地猜测哪些可以证明,哪些不能证明(即使没有访问静态检查器)。如另一个答案所述,静态检查器不进行过程间分析。因此,随着多线程变量访问的迫在眉睫(如在OP中),静态检查器只能有效地处理局部变量(如下所述)。

“局部变量”是指任何其他线程都无法访问的变量。这将包括在方法中声明或作为参数传递的任何变量,除非用refout修饰参数,或者该变量是在匿名方法中捕获的。

如果局部变量是值类型,则其字段也是局部变量(依此类推)。

如果局部变量是引用类型,则只能将引用本身(而不是其字段)视为局部变量。即使在方法中构造的对象也是如此,因为构造函数本身可能会泄漏对构造对象的引用(例如,对静态集合进行缓存)。

只要静态检查器不进行任何过程间分析,就可以在任何时候使对上述非局部变量所做的任何假设无效,因此在静态分析中将其忽略。

异常(exception)1:由于运行时知道字符串和数组是不可变的,因此只要字符串或数组变量本身是局部变量,它们的属性(例如Length)都需要进行分析。这不包括其他线程可更改的数组内容。

异常(exception)2:运行时可能知道数组构造函数不会泄漏对构造数组的任何引用。因此,在方法体内构造且未泄漏到方法外部的数组(作为参数传递给另一个方法,分配给非局部变量等)具有也可以视为局部变量的元素。

这些限制似乎相当繁重,我可以想象有几种方法可以改进它,但是我不知道已经做了什么。从理论上讲,这里还有一些其他事情可以使用静态检查器来完成。方便的人应该检查一下已完成和未完成的操作:
  • 它可以确定构造函数是否不泄漏对对象或其字段的任何引用,并将这样构造的任何对象的字段视为局部变量。
  • 可以对其他方法进行无泄漏分析,以确定在方法调用之后传递给方法的引用类型是否仍可以视为本地。
  • 用ThreadStatic或ThreadLocal装饰的变量可以被视为局部变量。
  • 可以使用选项来忽略使用反射修改值的可能性。这将允许引用类型上的私有(private)只读字段或静态私有(private)只读字段被视为不可变的。同样,启用此选项后,只能在lock(X){ /**/ }结构内部访问且不泄漏的私有(private)或内部变量X可以视为局部变量。但是,这些事情实际上会降低静态检查器的可靠性,因此有点困难。

  • 可能打开许多新分析的另一种可能性是,以声明方式将变量和使用它们的方法(递归地)分配给特定的唯一线程。这将是该语言的主要补充,但可能值得。

    关于c# - C#代码契约(Contract): What can be statically proven and what can't?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5026089/

    有关c# - C#代码契约(Contract): What can be statically proven and what can't?的更多相关文章

    1. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

      我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

    2. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

      我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

    3. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

      如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

    4. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

      在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

    5. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

      我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

    6. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

      在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

    7. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

      我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

    8. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

      我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

    9. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

      我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

    10. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

      关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

    随机推荐