具有未定义行为的分支是否可以被假定为不可访问并优化为死代码?

2024-03-29

考虑以下陈述:

*((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语句可以被优化掉。这种倒推的推理按照标准是允许的吗?


在给定程序中存在这样的语句是否意味着 整个程序未定义或该行为仅变得未定义 一旦控制流命中这个语句?

两者都不。第一个条件太强,第二个条件太弱。

对象访问有时是按顺序进行的,但标准描述了程序在时间之外的行为。丹维尔已经引用过:

如果任何此类执行包含未定义的操作,则此 国际标准对实施没有要求 使用该输入执行该程序(甚至不考虑 第一个未定义操作之前的操作)

这可以解释为:

如果程序的执行产生未定义的行为,则整个程序 未定义的行为。

因此,带有 UB 的 unreachable 语句不会给出程序 UB。一个可达语句(由于输入的值)永远不会达到,不会给程序提供 UB。这就是为什么你的第一个条件太强了。

现在,编译器一般无法判断什么具有 UB。因此,为了允许优化器对具有潜在 UB 的语句进行重新排序,如果定义了它们的行为,则可以重新排序,有必要允许 UB “及时返回”并在前一个序列点(或在 C 语言中)之前出错。 ++11 术语,用于 UB 影响在 UB 事物之前排序的事物)。所以你的第二个条件太弱了。

一个主要的例子是优化器依赖于严格的别名。严格别名规则的全部要点是,如果有问题的指针可能别名相同的内存,则允许编译器对无法有效重新排序的操作进行重新排序。因此,如果您使用非法别名指针,并且 UB 确实发生,那么它很容易影响 UB 语句“之前”的语句。对于抽象机来说,UB 语句还没有被执行。就实际的目标代码而言,它已经部分或全部执行。但该标准并没有尝试详细说明优化器对语句重新排序意味着什么,或者这对 UB 有何影响。它只是给予实施许可,只要它愿意,就可以出错。

您可以将其视为“UB 有一台时间机器”。

具体回答你的例子:

  • 仅当读取 3 时,行为才未定义。
  • 如果基本块包含肯定未定义的操作,编译器可以并且确实将代码消除为死代码。在不是基本块但所有分支都通向 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 https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2009-1897)本质上是因为它在取消引用空指针的模式下运行isn't应该是 UB,它预计会导致内核可以处理的已定义硬件异常。当启用优化时,gcc 需要使用-fno-delete-null-pointer-checks以提供超标准的保证。

附: “未定义行为何时发生?”这个问题的实际答案是“您计划当天出发前 10 分钟”。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有未定义行为的分支是否可以被假定为不可访问并优化为死代码? 的相关文章

  • 如何在C++中生成非常大的随机数

    我想使用 C 生成 0 2 64 范围内的非常大的随机数 我已经使用了 rand 函数 但它没有生成非常大的数字 有人可以帮忙吗 使用c 11 使用标准c 11的随机库 http en cppreference com w cpp nume
  • 无法使用c#更改视频捕获分辨率

    我正在尝试使用 C 中的 DirectShowNet 更改默认网络摄像头分辨率 据我所知 我需要通过调用 windows win32 api dll 中内置的 VideoInfoHeader 类来更改它以进行 avi 捕获 我有来自 Dir
  • 如何使用 Entity Framework 和 Identity 解决对象处置异常 ASP.NET Core

    我正在尝试编写一个控制器 该控制器接收来自 AJAX 调用的请求并通过 DBContext 对数据库执行一些调用 但是 当我发出命令时var user await GetCurrentUserAsynch 在对 DBContext 的任何调
  • 在 WCF 上重用我的 PagedList 对象

    问题 我有一个自定义集合PagedList
  • strtok() 使用安全吗[重复]

    这个问题在这里已经有答案了 我读到了很多负面的东西strtok 有人说它已经过时 有人说它不是线程安全的 等等 那么真相是什么 我可以使用吗strtok 它是线程安全的吗 Note 我正在使用 Visual C 您可以使用它 它是标准库的一
  • 信号与信号2

    我的应用程序可能会受益于使用 boost 的信号库之一而不是本土解决方案 该应用程序是多线程的 但执行信号处理的部分是单线程的 如果多线程不是问题 是否有任何理由更喜欢 Boost Signals2 而不是 Boost Signal Boo
  • 头文件中实现的函数的静态与内联

    我想到的方式inline在 C 中用于链接 作用域 我把它放在同一个篮子里extern and static对于全局对象 通常 对于在头文件中实现的函数 我的首选解决方案是将其设为静态 In Foo h static void foo Do
  • 如何通过 libwebsocket 发送异步数据?

    我正在将 Warmcat 的 libwebsocket C 库用于小型 Websocket 服务器 我已经启动并运行了这些示例 并且可以发送数据以响应从 websocket 接收数据 例如回显发送的反向字节 但是 我无法弄清楚如何在不使用
  • 我可以将 char 或 DateTime 设置为 null 吗?

    我可以将 null 设置为char数据类型 并且DateTime在 C 中 多谢你们 这是不可能的 它是一个值类型 使用 char myChar null DateTime myDate null 这相当于 Nullable
  • 从内存流播放视频文件

    只是好奇看看这是否可能 我有一个 Windows 应用程序 它从我的电脑上的 avi 文件读取所有字节 然后将其存储在 byte 中 现在我的内存中有 avi 文件 我想直接从内存将其加载到某种视频播放器控件中 我尝试过使用 wmplaye
  • 如何使用 CUDA/Thrust 对两个数组/向量根据其中一个数组中的值进行排序

    这是一个关于编程的概念问题 总而言之 我有两个数组 向量 我需要对一个数组 向量进行排序 并将更改传播到另一个数组 向量中 这样 如果我对 arrayOne 进行排序 则对于排序中的每个交换 arrayTwo 也会发生同样的情况 现在 我知
  • 如何在 Visual Basic DLL 和 C++ DLL 之间创建隔离/免注册 COM?

    我必须在 C DLL 中使用 VB COM DLL 我弄清楚了如何从 C DLL 访问 VB COM DLL 并且它可以工作 现在我遇到了一个问题 我必须使用隔离的 COM 免注册 COM 因为我无法在必须使用它的每台 PC 上注册 DLL
  • 如何调试.NET Windows Service OnStart方法?

    我用 NET 编写的代码仅在作为 Windows 服务安装时才会失败 该故障甚至不允许服务启动 我不知道如何进入 OnStart 方法 如何 调试 Windows 服务应用程序 http msdn microsoft com en us l
  • asp.net core http 如果没有内容类型标头,则删除 `FromBody` 忽略

    我在 http 中使用 bodyDELETE要求 我知道目前删除主体是非标准的 但是允许的 使用时出现问题HttpClient它不允许删除请求的正文 我知道我可以使用SendAsync 但我宁愿让我的 API 更加灵活 我希望这个机构是可选
  • 如何在 C++ 运行时更改 QML 对象的属性?

    我想在运行时更改 QML 对象的文本 我尝试如下 但文本仍然为空 这是后端类 class BackEnd public QObject Q OBJECT Q PROPERTY QString userFieldText READ userF
  • Windows 上本机 C++ 应用程序中的自动死代码检测?

    背景 我有一个用原生 C 编写的应用程序 花了几年的时间 大约有 60 KLOC 有很多函数和类已经死了 可能有 10 15 就像下面提出的类似的基于 Unix 的问题 我们最近开始对所有新代码进行单元测试 并尽可能将其应用于修改后的代码
  • 调试错误:在 vc++ 项目中使用 COM 时发生 所需的运行时?

    我为我的工作创建了一个 COM 组件 我也注册了该组件 在我的系统上 我有两个虚拟机工作站 在我的第一个工作站中 它运行良好 在我的第二个工作站中 它显示一个包含消息的错误框该程序需要一段时间并以不寻常的方式关闭 请联系应用程序管理员 我认
  • 如何重用具有稍微不同的 ProcessStartInfo 实例的 Process 实例?

    我有以下开始的代码robocopy https technet microsoft com en us library cc733145 aspx as a Process 我还需要进行数据库查询以确定每次需要复制哪些目录robocopy被
  • C - 获取外部IP地址

    我需要通过 C C 调用获取我的公共 IP 地址 我知道作为替代方案 我可以从 http whatismyip akamai com 等外部链接获取 我写了一个示例来获取外部IP地址 但我的程序没有返回外部 IP 地址 我正在获取内部 IP
  • C# PasswordDeriveBytes:似乎 Salt 并不重要

    可能我误解了什么 以下代码通过 CryptDeriveKey 使用两种不同的盐生成两个相等的密钥 这是控制台结果 盐1 21 3e 18 a3 9a 8b 5f gt 键 da 89 ea 3d 91 08 20 98 20 e9 dc 4

随机推荐

  • Flutter - 获取 SHA-1 证书 - Android Studio 3.2.1

    我正在尝试检索我的 Flutter 项目的 SHA 1 指纹证书 这通常可以通过进入 Android Studio 右侧的 Gradle 面板并单击signingReport 然而问题是 在 Flutter 中 它根本不显示 Gradle
  • Laravel 可以处理高流量应用程序吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我正在开发一个 PHP MySQL 社交网络项目 该项目将包含许多模块 部分 包括 用户系统 权限 配置文件 设置等 stackoverflow
  • Tomcat 9 的 Maven 插件

    除了 tomcat7 maven plugin 之外 我没有找到任何 tomcat maven plugin 我可以将其与 apache tomcat 9 0 0 M15 一起使用吗 您可以使用该插件部署到单独运行的 tomcat 9 Th
  • 自定义样式的 AlertDialog 的样式属性

    我正在尝试设计我的 AlertDialog 的样式 并且我已经能够通过样式和 xml 声明更改其中的大部分内容 但仍然存在一些问题 如何将标题栏周围的区域从黑色更改为我的自定义颜色 如何将外部背景更改为透明 阴影落在蓝色的外部部分 如何更改
  • “yes”这个程序有什么重要用途吗?

    当我第一次遇到yes nix 中的程序我想不出它有什么重要用途 这个程序是如何使用的 yes旨在自动化需要在采取行动之前确认的交互式程序 yes rm ri foo 大致相当于 rm rf foo 不同之处在于 f失败时也会继续
  • Rails 4 jQuery 与 javascript 冲突

    我正在尝试在 Rails 4 中制作一个应用程序 我正在挣扎 我正在尝试合并引导主题 但我遇到了供应商 JavaScript 和其余代码的问题 我认为问题可能与我的 application js 中的 jQuery 以及以 符号开头的供应商
  • 按名称实例化 Java lambda 函数

    我想在 Java 8 中创建一个 lambda 函数 获取它的类名 然后从它的类名再次实例化该函数 这就是我尝试的 import java util function Consumer public class SimpleLambda p
  • ajax 与常规表单数据的安全性

    只是想知道安全性的差异
  • Websphere Application Server 6.1(本地化):覆盖控制台消息的区域设置

    我已经安装了西班牙语版本的 RAD 7 5 基于 Eclipse Ganymede 3 4 0 我正在与Websphere 应用程序服务器 6 1 也是西班牙语 我遇到的问题是所有控制台消息都以西班牙语显示 但在我个人看来 翻译相当差 特别
  • 如何处理来自代理的额外 HTTP 标头?

    我们的环境需要使用出站代理来提供异地服务 通常这不是问题 在 Twilio 的这种情况下 返回的额外标头会破坏客户端 传出标头 POST 2010 04 01 Accounts FOO SMS Messages json HTTP 1 1
  • 如何提取双精度数的尾数

    我想将双精度数的尾数存储在变量中 我发布了一个代码来获取 double 的二进制表示形式 点击这里 https stackoverflow com questions 5670221 binary representation of a f
  • 使用 jQuery.getJson 获取 Web API [重复]

    这个问题在这里已经有答案了 我是 ASP NET Web API 的初学者 使用失败jQuery getJson to get ASP NET Web API 这失败了 var url http localhost 56110 api Va
  • 使用 JS / jQuery 启用/禁用 DOM 元素的事件

    我遇到了一个小问题 我花了很多时间来解决这个问题 与它的功能相比 这个问题相当糟糕 我的 DOM 中有标签 并且我已经使用 jQuery 将多个事件绑定到它们 var a a click data function 有时我想禁用其中一些元素
  • WordPress 重定向问题,标头已发送

    我想知道 根据下面的代码 我想把我的 wp redirect 函数放在哪里 因为它当前所在的位置除了 spazzes 和 sais 之外什么也不做 Warning Cannot modify header information heade
  • 处理器的 mpi 数量错误

    抱歉 我肯定犯了一个愚蠢的错误 但没有成功 我正在编译一个简单的 mpi hello world include
  • Google PageSpeed API dotnet .net

    我已经设置了一个基本的 C 应用程序 以便在我使用 Google Apis Pagespeedonline v2 nuget 包指定的网站上运行 PageSpeed 测试 设置非常简单 我有一个变量可以指定 url 然后将其传递到服务中 C
  • 保留 qw 中的空白

    有什么办法可以保留 qw 中的一些空白吗 例如 my a qw 1234 John Smith 123 Main St 将生成一个包含 6 个元素的数组 有什么方法可以 哦 我不知道 逃离空白以保留其中的一些 就像是 my a qw 123
  • 如何使用维基百科的 API 获取维基百科内容?

    我想获取维基百科文章的第一段 执行此操作的 API 查询是什么 请参阅本节中的MediaWiki API 文档 http www mediawiki org wiki API Properties revisions 2F rv 具体涉及获
  • 使用 knit-ess 进行 Polymode 编织 - 不想在 tex 文件名中包含“编织”

    我对 emacs 还很陌生 并且已经习惯在早期版本中使用 Sweave 现在我一直在使用polymode并使用knitr ess进行编织 但是 我想做两个定制 我希望生成的编织名称与文件名相同 即不是 filename writing te
  • 具有未定义行为的分支是否可以被假定为不可访问并优化为死代码?

    考虑以下陈述 char NULL 0 undefined behavior 它显然会调用未定义的行为 给定程序中存在这样的语句是否意味着整个程序未定义 或者只有当控制流命中该语句时行为才变得未定义 如果用户从不输入号码 以下程序是否会被明确