考虑以下语句:
*((char*)NULL) = 0; //undefined behavior
它显然调用了未定义的行为。给定程序中存在这样的语句是否意味着整个程序是未定义的,或者只有在控制流到达该语句时行为才变得未定义?
如果用户从不输入数字3,下面的程序会被很好地定义吗?
while (true) {
int num = ReadNumberFromConsole();
if (num == 3)
*((char*)NULL) = 0; //undefined behavior
}
或者无论用户输入什么,它都是完全未定义的行为?
另外,编译器可以假设未定义的行为永远不会在运行时执行吗?这将允许及时向后推理:
int num = ReadNumberFromConsole();
if (num == 3) {
PrintToConsole(num);
*((char*)NULL) = 0; //undefined behavior
}
在这里,编译器可以推断万一 num == 3 我们将始终调用未定义的行为。因此,这种情况一定是不可能的,也不需要打印数字。可以优化整个 if 语句。这种逆向推理按标准是允许的吗?
最佳答案
Does the existence of such a statement in a given program mean that the whole program is undefined or that behavior only becomes undefined once control flow hits this statement?
两者都没有。第一个条件太强,第二个条件太弱。
对象访问有时是按顺序进行的,但标准描述了程序在时间之外的行为。 Danvil 已引用:
if any such execution contains an undefined operation, this International Standard places no requirement on the implementation executing that program with that input (not even with regard to operations preceding the first undefined operation)
这可以解释为:
If the execution of the program yields undefined behavior, then the whole program has undefined behavior.
因此,带有 UB 的不可访问语句不会给程序 UB。一个可到达的语句(由于输入的值)永远不会到达,不会给程序 UB。所以你的第一个条件太强了。
现在,编译器一般不能分辨什么有 UB。因此,为了允许优化器对具有潜在 UB 的语句重新排序,如果它们的行为被定义,则有必要允许 UB“及时返回”并在前一个序列点之前出错(或在 C++11 术语,UB 影响在 UB 事物之前排序的事物)。因此,您的第二个条件太弱了。
一个主要的例子是优化器依赖于严格的别名。严格别名规则的重点是允许编译器重新排序操作,如果有问题的指针可能对相同的内存进行别名,则无法有效地重新排序。因此,如果您使用非法别名指针,并且确实发生了 UB,那么它很容易影响 UB 语句“之前”的语句。就抽象机而言,UB 语句尚未执行。就实际的目标代码而言,它已部分或全部执行。但是该标准并没有尝试详细说明优化器对语句重新排序意味着什么,或者这对 UB 有什么影响。它只是让实现许可在需要时尽快出错。
你可以把它想象成,“UB 有一台时间机器”。
专门回答你的例子:
PrintToConsole(3) 以某种方式知道一定会返回。它可能会引发异常或其他任何情况。与您的第二个类似的示例是 gcc 选项 -fdelete-null-pointer-checks,它可以采用这样的代码(我没有检查过这个具体示例,认为它说明了总体思路):
void foo(int *p) {
if (p) *p = 3;
std::cout << *p << '\n';
}
并将其更改为:
*p = 3;
std::cout << "3\n";
为什么?因为如果 p 为 null 则代码无论如何都有 UB,因此编译器可能会假定它不为 null 并相应地进行优化。 linux内核绊倒了这个(https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2009-1897)本质上是因为它在取消引用空指针不应该是UB的模式下运行,预计会导致内核定义的硬件异常可以处理。启用优化后,gcc 需要使用 -fno-delete-null-pointer-checks 以提供超出标准的保证。
附: “未定义的行为何时发生?”这个问题的实际答案。是“在您计划出发前 10 分钟”。
关于c++ - 是否可以假定具有未定义行为的分支无法访问并将其优化为死代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23153445/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
在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
查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>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
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server