是否需要在同一环境中使用同一编译器对同一程序进行编译之间保持一致的未指定和未定义行为?

     2023-02-21     134

关键词:

【中文标题】是否需要在同一环境中使用同一编译器对同一程序进行编译之间保持一致的未指定和未定义行为?【英文标题】:Are unspecified and undefined behavior required to be consistent between compiles of the same program with the same compiler in the same environment? 【发布时间】:2011-03-04 20:19:45 【问题描述】:

让我们假设我的程序包含 C++ 标准规定为未指定行为的特定构造。这基本上意味着实现必须做一些合理的事情,但允许不记录它。但是,每次编译具有未指定行为的特定构造时,实现是否需要产生相同的行为,还是允许在不同的编译中产生不同的行为?

未定义的行为呢?假设我的程序包含一个符合标准的 UB 结构。允许实现展示任何行为。但是,在相同环境中具有相同设置的相同编译器上的相同程序的编译之间,这种行为会有所不同吗?换句话说,如果我在文件 X.cpp 的第 78 行取消引用一个空指针,并且在这种情况下实现对驱动器进行格式化,这是否意味着在重新编译程序后它也会这样做?

问题是……我用相同的编译器在相同的环境中使用相同的编译器设置编译相同的程序。声明为未指定行为和未定义行为的构造会在每次编译时产生相同的行为,还是允许它们在编译之间有所不同?

【问题讨论】:

【参考方案1】:

如果它是未定义的行为,那么本质上将发生的事情是未定义的,您不能指望它在任何情况下都是相同的。

另一方面,未指定的行为由各个供应商决定如何实施,例如,如果语言规范中存在歧义。这在编译和运行之间是一致的,但在不同的供应商之间不一定是一致的。因此,例如,当您仅使用 Visual Studio 构建时依赖未指定的行为是可以的,但如果您尝试将代码移植到 gcc,它可能会失败或产生与您预期不同的行为。

【讨论】:

你只回答了一半问题。未指明的行为呢? :) 我认为未指定的行为也不需要任何形式的一致性。我相信展开调用函数的循环的编译器可能具有例如如果这样做会改善寄存器分配,则第一次或最后一次通过循环以不同的顺序评估参数。【参考方案2】:

不,这是标准中存在未定义/实现定义行为的部分原因。不保证在同一台计算机上多次编译同一源代码(例如,使用不同的优化标志)时未定义的行为是相同的。

委员会显然更喜欢定义明确的行为。当委员会认为某个概念存在多个实现时,实现定义的行为就存在,并且没有理由在所有情况下都偏爱一个。当委员会认为在合理的实现下难以兑现任何承诺时,就会出现未定义的行为。

在许多情况下,未定义的行为被实现为没有检查的东西。然后,该行为取决于操作系统,如果有的话,并且它是否注意到发生了不符合 kosher 的事情。

例如,取消引用不属于您的内存是未定义的。一般来说,如果你这样做,操作系统会杀死你的程序。但是,如果星星排列得恰到好处,您可以设法取消引用您在 C++ 规则下不拥有的内存(例如,您不是从 new 获得的,或者您已经从 deleted 获得它)但是操作系统相信你拥有。有时你会崩溃,有时你会破坏程序中其他地方的内存,有时你会在未被发现的情况下逃脱(例如,如果内存没有被归还)。

竞态条件被认为是未定义的,它们因在程序的不同运行期间不同而臭名昭著。如果您的操作系统没有注意到,每次您破坏堆栈时,您可能会得到不同的行为。

deletes 未定义。通常它们会导致崩溃,但它们未定义的事实意味着您不能依赖崩溃的东西。

【讨论】:

【参考方案3】:

未定义的行为在同一程序的运行之间可能会有所不同,甚至在同一程序运行中相同代码的执行之间也会有所不同。例如,未初始化(自动)变量的值是未定义的,然后它的实际值就是恰好在内存中那个位置的任何值。显然,这可能会有所不同。

编辑:

这也适用于未指定的行为。例如,函数参数的求值顺序是未指定的,所以如果它们有副作用,这些副作用可以以任何顺序发生。这可能会打印“Hi!Ho!”或“嗨!嗨!”:

f( printf("Hi!"), printf("Ho!") );

这也可能因执行而异。正如标准所说: “因此,对于给定程序和给定输入,抽象机的一个实例可以具有多个可能的执行顺序。”不同之处在于 undefined 行为,任何事情都可能发生:计算机可能会爆炸、重新格式化磁盘或其他任何事情。如果行为未指定,则不允许计算机爆炸。

还有实现定义的行为,比如sizeof(int)的值。对于同一个编译器,这必须始终相同。

【讨论】:

这个解释简洁、合理,遵循“展示,不讲”的原则。未指明的行为呢?【参考方案4】:

但是这种行为在 编译相同的程序 具有相同设置的相同编译器 一样的环境?

是的。

换句话说,如果我取消引用 文件 X.cpp 中第 78 行的空指针 和实现格式 在这种情况下开车是否意味着 它会在程序结束后做同样的事情 重新编译了吗?

未定义行为的结果几乎总是由编译器发出的代码以语言设计者未指定的方式与操作系统和/或硬件交互引起的。因此,如果您取消引用 NULL 指针,发生的事情实际上与编译器无关,而是取决于底层操作系统/硬件如何处理无效的内存访问。如果操作系统/硬件总是以一致的方式处理这个问题(例如通过陷阱),那么您可以期望 UB 是一致的,但这与语言或编译器无关。

【讨论】:

【参考方案5】:

当使用不同的优化级别或使用或不使用调试模式进行编译时,许多此类行为的实现方式不同。

【讨论】:

【参考方案6】:

未指定和未定义的行为不能保证在已编译程序的单独运行之间保持一致。仅这一点就已经使单独的编译之间的一致性概念完全没有意义。

此外,可能值得添加的是,未定义的行为可以通过阻止程序编译在编译阶段表​​现出来。

【讨论】:

【参考方案7】:

值得注意的是,即使在今天,C++ 标准的指定行为的实现在不同的编译器中也不是 100% 相同的。鉴于此,期望未指定或未定义的行为与编译器无关是不合理的。如果您只遵守标准,您就有最好的机会编写可移植的代码。

【讨论】:

我不是在问编译器不可知论。在我的问题中,编译器每次都是一样的,设置是一样的,C++代码是一样的。 在这种情况下,是的,通常相同的输入会产生相同的输出。我见过一些案例,当我们更改看似不相关的一段代码或编译器设置时,我们依赖代码中的某些副作用惊人地失败了。 (IIRC,这些涉及非 100% 支持的效果模板实例化和严格的别名。)【参考方案8】:

这就是将其指定为未定义的目的......这意味着不知道会发生什么,无论是在不同的平台上,还是在相同的平台上(重复测试)。

【讨论】:

【参考方案9】:

我不知道未指明的行为(但从名称来看,也许它在任何地方都做同样的坏/坏事,只是没有人真正知道它到底做了什么)。但是对于未定义的行为,我认为这个行为可能在平台或编译器之间有很大不同。我在 Solaris 上看到了一些非常奇怪的核心转储,但在 Ubuntu 等上没有发生。

【讨论】:

我问的是在同一系统上使用相同的编译器和相同的设置(所有设置)重新编译。 抱歉,错过了。无论如何,我相信你不能(或至少不应该)依赖它。它只是未定义/未指定,这意味着几乎任何事情都可能发生。

在同一个应用上使用两个 Facebook 应用 ID 进行测试

...】:为了在不修改生产数据的情况下测试Facebook事件,我需要在我的iOS应用程序中使用第二个Facebook应用程序ID。我想在我的持续集成环境中自动完成。发布方案->将具有生产Facebook应用程序ID。调试 查看详情

无法使用在同一类中使用成员函数的线程进行编译

】无法使用在同一类中使用成员函数的线程进行编译【英文标题】:Cannotcompilewiththreadthatusesmemberfunctionwithinsameclass【发布时间】:2020-01-0918:11:49【问题描述】:我正在尝试从同一个类中创建一个调用成员函数的线程。我见过一些... 查看详情

在同一代码中多次使用同一 SQLCommand 实例进行多次查询?

】在同一代码中多次使用同一SQLCommand实例进行多次查询?【英文标题】:usingthesameinstanceofSQLCommandmorethanonetimeinthesamecodeformorethanonequery?【发布时间】:2013-11-1418:23:49【问题描述】:我对使用为什么不能在同一代码中多次使用同一... 查看详情

是否允许 C++ 编译器发出编译同一程序的不同机器代码?

】是否允许C++编译器发出编译同一程序的不同机器代码?【英文标题】:IsaC++compilerallowedtoemitdifferentmachinecodecompilingthesameprogram?【发布时间】:2011-03-0411:48:38【问题描述】:考虑一种情况。我们有一些特定的C++编译器、一组特定... 查看详情

是否允许 C++ 编译器发出编译同一程序的不同机器代码?

】是否允许C++编译器发出编译同一程序的不同机器代码?【英文标题】:IsaC++compilerallowedtoemitdifferentmachinecodecompilingthesameprogram?【发布时间】:2011-03-0411:48:38【问题描述】:考虑一种情况。我们有一些特定的C++编译器、一组特定... 查看详情

如何从命令提示符对同一文件夹中的多个文件进行 tesseract?

...中的多个文件进行Tesseract。foriin*.tif;dotesseract$iouttext;done;是否有人对如何在运行Win 查看详情

是否可以在 Oracle10g 中的同一查询中进行插入和删除?

】是否可以在Oracle10g中的同一查询中进行插入和删除?【英文标题】:IsitpossibletodoInsertandDeleteinasamequeryinOracle10g?【发布时间】:2011-12-3007:09:30【问题描述】:我的要求是,我需要根据某些条件将我的SOURCE表中的一些记录插入到TA... 查看详情

c#编译过程

...可移植性。2.程序执行时,IL被CLR捕获,CLR激活内部的JIT编译器,将伪代码编译成针对特定CPU的机器语言。JIT:即时编译,在代码需要运行的时候才将对应的IL编译为本机指令,然后把结果保存到(GAC)用于将来对同一方法的调用... 查看详情

需要使用同一连接从服务器进行多次推送

】需要使用同一连接从服务器进行多次推送【英文标题】:Needmultiplepushfromserverusingsameconnection【发布时间】:2018-08-2112:14:26【问题描述】:我正在尝试实现一个简单的UI,它将显示在我的服务器控制台中写入的日志。已搜索但找... 查看详情

是否可以在同一应用程序中浏览不同的子域或基本 URL 而无需在 React 中刷新页面?

】是否可以在同一应用程序中浏览不同的子域或基本URL而无需在React中刷新页面?【英文标题】:Isitpossibletonavigateacrossdifferentsub-domainsorbaseURLsinsameapplicationwithoutrefreshingthepageinReact?【发布时间】:2021-04-1306:24:28【问题描述】:我... 查看详情

使用同一个表中的并集对结果进行排序

...thesametable【发布时间】:2017-03-0120:33:24【问题描述】:我需要先在列表中显示一组结果,然后再显示下表中的其余结果。我尝试过SQL:howtouseUNIONandorderbyaspecificselect?,但在我的情况下似乎不起作用。我的查询如下所示SELECT*FROM(SELEC... 查看详情

我们如何在同一spring应用程序中同时添加jwt和基本身份验证?(代码片段)

...用都应该绕过jwt身份验证,并且应该使用基本身份验证。是否可以有2个Web安全配置器或其他?我们如何实现这一目标?我能够从JWT身份验证中排除特定的url,但是如何要求spring进行基本身份验证?TIA答案我们不能同时做两个。... 查看详情

对同一文件的不同部分使用不同的 C++ 标准

...们使用C++11作为我们开发的基线(针对多个平台)。最近需要在我们的代码库中进行一些更改,突然需要一些C++17功能。到目前为止一切都很 查看详情

zend 守卫解码(不是同一个问题)

...我知道旧帖子,或者至少知道zend的旧版本(喜欢,他们是否对核心进行了很多更新,所以它不再容易了,还是同样的事情?有大量的网站可以解码,但在最新版本中这很容易吗?顺便说一句,你不需要发布“没有脚本不能被完... 查看详情

并发编程,高速缓存,原子操作,指令重排序(代码片段)

...一次期望变更。三、关于指令重排序所谓指令重排序,即编译器为了优化性能对需要执行的程序语段进行重排序。当然,重排序在不涉及并发的操作中,是有益的,否则编译器也不会有着个功能。但是,当进行并发编程时,我们... 查看详情

对多个应用使用同一个苹果应用商店证书

...:22【问题描述】:您好,我有多个应用程序,并想知道我是否需要为每个应用程序单独创建一个应用程序商店证书。真正的问题是所有这些证书都具有相同的名称,我以后将无法知道哪个证书属于哪个应用程序。寻找你的答案,... 查看详情

Spring - 是不是可以在同一个应用程序中使用多个事务管理器?

...ng-Isitpossibletousemultipletransactionmanagersinthesameapplication?Spring-是否可以在同一个应用程序中使用多个事务管理器?【发布时间】:2011-05-2407:32:25【问题描述】:我是Spring新手,我想知道是否可以在同一个应用程序中使用多个事务管理... 查看详情

如何在同一版本中使用更低和更高的 API 调用? [复制]

...开发一个简单的应用程序,它包含两个功能。第一个函数需要3.0API(或更低版本)的一些方法,第二个函数需要4.4API。我想要一个版本!如果运行环境是4.4的Android,应用程序 查看详情