通过易失性引用/指针访问声明的非易失性对象是否会为所述访问赋予易失性规则?

2024-05-05

这将是一篇很长的文章,为了将其置于上下文中并提供尽可能多的信息,我必须浏览各种链接和引用 - 这通常是我们进入 C/C++ 标准兔子洞的唯一方法。如果您对这篇文章有更好的引用或任何其他改进,请告诉我。但先总结一下,你可以责怪@zwol对我来说发布这个;-) https://stackoverflow.com/questions/38230856/is-the-definition-of-volatile-this-volatile-or-is-gcc-having-some-standard-co#comment63893828_38231071_目的是从两个命题中找出真相:

  • C 和(通过导入;参见注释)C++ 标准要求通过volatile * or volatile &必须引用最初声明的对象volatile为了有volatile语义?
  • Or 正在访问一个非volatile- 合格的对象通过volatile指针/引用足以/应该使所述访问的行为就像声明了对象一样volatile?

不管怎样,如果(看起来)措辞与意图相比有些模糊——我们可以说清楚吗在标准本身中?

第一种相互排斥的解释更为普遍,这并非完全没有根据。然而,我希望表明,存在大量支持第二点的“合理怀疑”——尤其是当我们回顾基本原理和工作组文件中的一些先前段落时。

公认的智慧:所引用的对象本身必须已声明volatile

昨天的热门问题“不稳定”的定义是否如此不稳定,或者 GCC 是否存在一些标准合规性问题? https://stackoverflow.com/questions/38230856通过假设出现volatile参考将赋予volatile行为在非volatile所指的——但发现它没有,或者在不同程度上以不可预测的方式发生了。

接受的答案最初得出的结论是,只有所声明的引用类型才重要。这和大多数评论似乎都同意,正如我们所熟知的,等效原则正在发挥作用const:行为只会是volatile(或根本定义)如果引用具有相同的cv- 被推荐对象的资格:

该段落中的关键词是对象。volatile sig_atomic_t flag;是一个易失性对象。*(volatile char *)foo仅仅是通过易失性限定的左值进行访问,并且标准不要求具有任何特殊效果. – zwol https://stackoverflow.com/users/388520/zwol

这种解释似乎被广泛接受,正如对这个类似但希望不重复的问题的答复所示:指向非易失性对象的易失性指针的行为要求 https://stackoverflow.com/questions/28654418/requirements-for-behavior-of-pointer-to-volatile-pointing-to-non-volatile-object但即便如此,也存在不确定性:在答案说“不”之后,它又说“也许”!无论如何……让我们检查一下标准,看看“不”的依据是什么。

标准说了什么...或没有说什么

C11, N1548,§6.7.3: 而很明显访问一个对象是UB定义为 volatile or const通过不共享所述限定符的指针进行类型...

6如果尝试修改用 a 定义的对象const- 通过使用带有非的左值来限定类型const-限定类型,行为未定义。如果试图参考用 a 定义的对象volatile-合格类型通过使用非左值volatile-限定类型,行为未定义。(133)

...该标准似乎没有明确提到相反的情况,即volatile。另外,在总结的时候volatile及其操作,现在讨论一个对象has volatile-合格类型:

7 An 对象具有volatile-合格类型可能会以实现方式未知的方式进行修改或具有其他未知的副作用。因此,引用此类对象的任何表达式都应严格根据抽象机的规则进行评估,如 5.1.2.3 中所述。此外,在每个序列点,最后存储在对象中的值应与抽象机规定的值一致,除非被前面提到的未知因素修改。(134)什么构成对具有volatile-限定类型是实现定义的。

我们是否假设“has”等同于“被定义为”?或者可以“有” http://1.bp.blogspot.com/-CzqzzBV2tMk/TxBM3ar18MI/AAAAAAAAPm0/6faLPO9BM8w/s1600/i-can-has-cheezburger.jpg引用对象和引用限定符的组合?

一位评论者用这样的措辞很好地总结了这个问题:

From n1548§6.7.3 ¶6 该标准使用短语“使用易失性限定类型定义的对象”来区分它与“具有易失性限定类型的左值”。不幸的是,这种“定义的对象”与“左值”的区别没有继续下去,然后标准使用“具有 volatile 限定类型的对象”,并表示“什么构成对具有 volatile 限定类型的对象的访问”是实现定义的”(为了清楚起见,可以说“左值”或“定义的对象”)。那好吧。 –迪特里希·埃普 https://stackoverflow.com/users/82294/dietrich-epp

同一部分的第 4 段似乎很少被引用,但很可能是相关的,我们将在下一节中看到。

合理怀疑:是/曾经是volatile旨在赋予的指针/引用volatile其取消引用的语义?

上述答案有一个评论,其中作者引用了委员会早些时候的声明,对“参考必须匹配所指”的想法提出了质疑:

有趣的是,里面有一句话[C99 基本原理volatile] 这意味着委员会meant for *(volatile T*)x强制该人访问x被视为挥发性的;但标准的实际措辞并没有达到这一点。 – 兹沃尔

我们可以从上述第二个线程中找到有关这一基本原理的更多信息:指向非易失性对象的易失性指针的行为要求 https://stackoverflow.com/questions/28654418/requirements-for-behavior-of-pointer-to-volatile-pointing-to-non-volatile-object

另一方面,这个帖子 http://bytes.com/topic/c/answers/221923-cast-volatile引用《国际标准的基本原理——编程语言——C》的 6.7.3:

将值强制转换为限定类型没有任何效果;资格 (例如,易失性)不会对访问产生任何影响,因为它已经发生 在案件发生之前。如果需要访问非易失性对象 使用易失性语义,该技术是将地址转换为 对象到适当的指针限定类型,然后取消引用 那个指针。

philipxy

并从那个字节线程 http://bytes.com/topic/c/answers/221923-cast-volatile,我们称为 C99 s6.7.3 p3 - 又名 C11 的 p4 - 以及此分析:

该段落位于理由文件第 6.7.3.1 节之前。如果您还需要引用标准文档本身,请引用6.7.3 p3:

与限定类型关联的属性仅对左值表达式有意义。

表达方式(volatile WHATEVER) non_volatile_object_identifier is not左值,因此“易失性”限定符毫无意义。

相反,表达式* (volatile WHATEVER *) & non_volatile_object_identifier is左值(它可以放在赋值语句的左侧),因此 'volatile' 限定符的属性在这种情况下具有其预期含义。

蒂姆·伦奇

有一个very支持这一想法的具体论证,特别是关于第一个相关问题,工作组论文N1381 http://open-std.org/jtc1/sc22/wg14/www/docs/n1381.pdf。本文介绍了附件memset_s()做OP想要的事情 - 保证内存的非省略填充。在讨论可能的实现时,它似乎支持这样的想法 - 通过省略陈述任何要求 - 使用volatile改变非指针volatile object should根据生成代码指针的限定符,无论所引用的对象是什么......

  1. 独立于平台的“secure-memset”解决方案:
void *secure_memset(void *v, int c , size_t n) {
    volatile unsigned char *p = v;
    while (n--) *p++ = c;
    return v;
}

这种方法将防止内存清理被优化掉,并且它应该可以在任何符合标准的平台上运行。

...并且注意编译器不这样做...

最近有通知称一些编译器不总是遵守标准而违反了标准volatile预选赛。

谁是对的?

那太累了。这里当然有很大的解释空间,具体取决于您碰巧读过哪些文档,哪些没有读过,以及您选择如何解释许多不够具体的单词。显然有些地方出了问题:要么:

  • 基本原理和 N1381 的措辞错误或随意,或者
  • 它们被特别追溯无效......或
  • 该标准的措辞错误或随意。

我希望我们能够比过去围绕此事的所有含糊和猜测做得更好,并得到一份更结论性的声明记录在案。为此,我们非常欢迎专家提供任何进一步的资料和想法。


通过易失性引用/指针访问声明的非易失性对象是否会为所述访问赋予易失性规则?

volatile在 C 和 C++ 中并不意味着同样的事情。 C++ 标准使得通过易失性左值进行的访问变得可观察。 [1] 它表示它希望这与 C 行为相同。这就是 C 基本原理中描述的行为。尽管如此,C 标准表示对 volatile 声明的对象的访问是可观察的。 (请注意,通过非易失性左值访问易失性声明的对象是未定义的。)

However.有一个缺陷报告,基本上得到了委员会的同意(尽管仍然开放),该标准应该说,并且其意图一直是,并且实现总是反映出,重要的不是对象的波动性(根据标准),但访问(的左值)的波动性(根据基本原理)。

C11 版本 1.10 的缺陷报告摘要 日期:2016 年 4 月DR 476 http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_476左值的易失性语义 04/2016 Open

当然,对可观察行为所做的事情取决于实现。

确实没有任何歧义。只是人们不敢相信C 标准行为可能就是这样,因为这不是历史上的用法volatile(当地址文字左值被视为易失性对象时),如基本原理所预期的那样,如编译器之前和之后所实现的那样,如 C++ 标准所解释和描述的那样,如 DR 中所更正的那样。同样,该标准很明确,因为它没有说非易失性访问是可观察的,所以它们不是。 (“副作用”是定义评估偏序时使用的术语。)

[1] 或者至少希望现在是这样。来自评论下划线_d https://stackoverflow.com/users/2757035/underscore-d:

对于 C++,另请参阅P0612R0:注意 CH 2:易失性 http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0612r0.html, which 本月通过 https://isocpp.org/blog/2017/03/2017-03-post-kona-mailing-available清理 C++ 标准中一些关于“易失性对象”的剩余讨论,当真正通过易失性左值访问是它的含义(大概/希望是 C 的含义)。

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

通过易失性引用/指针访问声明的非易失性对象是否会为所述访问赋予易失性规则? 的相关文章

  • 以相反的顺序迭代可变参数模板参数

    如果我手动反转传递给它的模板参数的顺序 以下代码将起作用 template
  • 更快的算法来计算有多少数字可以被范围内的特定整数整除

    int a b c d 0 cin gt gt a gt gt b gt gt c for int i a i lt b i if i c 0 d cout lt
  • SetWindowsHookEx 函数返回 NULL

    我正在研究 DLL 注入 但收到错误如下 挂接进程失败 87 参数不正确 目标进程和dll都是64位的 注入代码为 BOOL HookInjection TCHAR target TCHAR dll name https msdn micr
  • 切换图片框可见性 C#

    为什么图片框控件的可见性属性在这里不起作用 我最初将它们设置为 false 以便在屏幕加载时它们不可见 但后来我想切换这个 我已完成以下操作 但似乎不起作用 这是一个 Windows 窗体应用程序 private void Action w
  • 返回 int& 的函数[重复]

    这个问题在这里已经有答案了 我在网上查了一下发现一篇试图解释的文章std move和右值 http thbecker net articles rvalue references section 01 html并发现了一些我实在无法掌握的东
  • 在运行时设置 DataGridView 上的 DataFormatString?

    是否可以在运行时设置 ASP NET DataGridView 中的列或单元格的 DataFormatString 属性 这应该有效 BoundField priceField grid Columns 0 as BoundField pr
  • 如何使用汇编获取BIOS时间?

    我正在从头开始实现一个小型操作系统 用于教育目的 现在 我想使用汇编来获取 BIOS 时间 我对此进行了很多搜索 但找不到任何代码示例来执行此操作 如果有人可以提供任何参考或代码示例或与此相关的任何内容 我将非常感激 See 时钟中断 1a
  • C# 中附加/分离事件处理程序的不同方式有什么区别

    我的问题有两个部分 首先 我们可以通过以下两种方式附加事件处理程序 myObject MyEvent new EventHandler MyHandler myObject MyEvent MyHandler 据我了解 这两者是等价的 在第
  • rand() 播种与 time() 问题

    我很难弄清楚如何使用 rand 并使用 Xcode 用 time 为其播种 我想生成 0 到 1 之间的随机十进制数 该代码为我提供了元素 1 和 2 看似随机的数字 但元素 0 始终在 0 077 左右 有什么想法吗 我的代码是 incl
  • 将 C# 反射代码移植到 Metro-Ui

    我正在尝试移植使用反射的现有 C 类 通用工厂 但我无法编译这段代码 Type types Assembly GetAssembly typeof TProduct GetTypes foreach Type type in types i
  • 特定设备的不同字体大小

    我目前正在开发通用应用程序 我需要分别处理移动设备和桌面的文本框字体大小 我找到了一些方法 但都不能解决问题 使用 VisualStateManager 和 StateTrigger 为例
  • 抽象类或接口。哪种方式是正确的?

    有两种方法可以选择抽象类或接口 微软解决方案和Oracle解决方案 微软 设计指南 请使用抽象 在 Visual Basic 中为 MustInherit 类而不是接口来将协定与实现分离 http msdn microsoft com en
  • 如何使用泛型类型的 DataContractSerializer 编写自定义序列化器?

    我想编写一个自定义序列化器 用于将会话状态存储到Azure 缓存 预览版 这意味着这个自定义序列化器必须实现IDataCacheObjectSerializer 如果我错了 请告诉我 我需要编写这个自定义序列化程序的原因是我需要序列化一些包
  • 指示泛型返回动态类型的对象

    这个问题是我原来问题的后续问题here https stackoverflow com questions 2541184 using a type object to create a generic 假设我有以下泛型类 简化 class
  • 数据损坏 C++ 和 Python 之间的管道

    我正在编写一些代码 从 Python 获取二进制数据 将其通过管道传输到 C 对数据进行一些处理 在本例中计算互信息度量 然后将结果通过管道传输回 Python 在测试时 我发现如果我发送的数据是一组尺寸小于 1500 X 1500 的 2
  • 无法通过 LINQ to Entities 使用某些功能?

    我正在尝试使用 LINQ 查询在项目上实现搜索功能 由于数据有时包含带有重音符号和其他符号的字符 因此我创建了一种方法来删除这些字符以进行搜索 这是我的代码 var addresses from a in db Addresses join
  • 将 bignum 类型结构转换为人类可读字符串的有效方法是什么?

    我有一点问题 为了增长我的 C 知识 我决定尝试实现一个基本的 bigint 库 bigint 结构的核心将是一个 32 位整数数组 选择它们是因为它们适合寄存器 这将允许我在数字之间进行操作 这些操作将在 64 位整数中溢出 这也将适合寄
  • 微软语音识别速度

    我正在使用微软的语音识别器开发一个小型练习应用程序 对于我正在做的事情来说 我似乎无法让它足够快地识别单个单词 我希望能够正常说话 系统将从我所说的内容中抓取 关键字 并生成一个字符串 目前我正在使用 5 个单词的自定义语法 红 蓝 黄 绿
  • 如何将 CSV 文件读入 .NET 数据表

    如何将 CSV 文件加载到System Data DataTable 根据CSV文件创建数据表 常规 ADO net 功能是否允许这样做 我一直在使用OleDb提供者 但是 如果您正在读取具有数值的行 但希望将它们视为文本 则会出现问题 但
  • 为什么 C# 接口名称前面加上“I”

    这种命名约定背后的基本原理是什么 我没有看到任何好处 额外的前缀只会污染 API 我的想法与康拉德一致response https stackoverflow com a 222502 9898与此相关的question https sta

随机推荐