c - 退出状态是可观察的行为吗?

标签 c language-lawyer main exit exit-code

C 2018 5.1.2.3 6 说:

The least requirements on a conforming implementation are:

  • Accesses to volatile objects are evaluated strictly according to the rules of the abstract machine.

  • At program termination, all data written into files shall be identical to the result that execution of the program according to the abstract semantics would have produced.

  • The input and output dynamics of interactive devices shall take place as specified in 7.21.3. The intent of these requirements is that unbuffered or line-buffered output appear as soon as possible, to ensure that prompting messages actually appear prior to a program waiting for input.

This is the observable behavior of the program.



从表面上看,这不包括程序的退出状态。

关于exit(status) , 7.22.4.4 5 说:

Finally, control is returned to the host environment. If the value of status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned. If the value of status is EXIT_FAILURE, an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined.



标准没有告诉我们这是可观察行为的一部分。当然,这个exit没有意义行为纯粹是对 C 的抽象机器的描述;将值返回给环境没有意义,除非它在环境中是可观察的。所以我的问题不是退出状态是否可观察,而是这是否是 C 标准对可观察行为的定义中的缺陷。或者在适用的标准中是否有其他文字?

最佳答案

我认为可以将这些拼凑起来,看看答案属于第 5.1.2.3.6 节的第一个要点:

Accesses to volatile objects are evaluated strictly according to the rules of the abstract machine



进一步看,第 3.1 节将“访问”定义为:

to read or modify the value of an object



和 § 3.15 将“对象”定义为:

region of data storage in the execution environment, the contents of which can represent values



奇怪的是,该标准没有包含“ volatile 对象”的定义。它确实包含第 6.7.3.6 节中“具有 volatile 限定类型的对象”的定义:

An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3.



推断具有 volatile 限定类型的对象具有该限定来准确地通知编译器它实际上是一个 volatile 对象似乎并非没有道理,所以我认为使用这种措辞并不过分“ volatile 对象”本身定义的基础,并将 volatile 对象定义为可以以实现未知的方式修改或具有其他未知副作用的对象。

§ 5.1.2.3.2 对“副作用”的定义如下:

Accessing a volatile object, modifying an object, modifying a file, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment.



所以我认为我们可以将其拼凑如下:
  • 返回要返回宿主环境的退出状态是
    显然是执行环境状态的变化,因为
    接收后的执行环境,例如,EXIT_SUCCESS , 必然处于不同的状态
    如果它收到,例如,EXIT_FAILURE .返回导出
    因此,状态是第 5.1.2.3.2 节中的副作用
  • exit()是一个执行此操作的函数,因此调用 exit()因此是
    本身也是第 5.1.2.3.2 节的副作用。
  • 该标准显然没有给我们提供内部工作的细节exit()或者什么机制exit()将用于将该值返回到
    宿主环境,但假设访问
    不会涉及对象,因为对象是数据区域
    存储在其内容可以表示的执行环境中
    值,退出状态是一个值。
  • 由于我们不知道宿主环境会做什么(如果有的话)
    为了响应状态的变化(尤其是因为我们的程序
    将在它发生之前退出),此访问具有未知的一面
    效果,因此访问的对象是 volatile 对象。
  • 自调用 exit()访问一个 volatile 对象,它是可观察的
    根据第 5.1.2.3.6 节的行为。

  • 这与对具有 volatile 限定类型的对象的正常理解是一致的,即如果我们不能确定不需要的副作用将被省略,因为可观察的行为(在正常的日常意义上),我们就不能优化对这些对象的访问) 可能会受到影响。在这种情况下,当然没有 volatile 限定类型的可见对象,因为 volatile 对象是问题由 exit() 内部访问。 , 和 exit()显然甚至不需要用 C 编写。但毫无疑问,似乎有一个 volatile 对象,第 5.1.2.3 节特别(三次)提到了 volatile 对象,而不是 volatile 限定类型的对象(以及第 6.2.4.2 节,这是标准 volatile 对象中唯一被引用的地方。)

    最后,这似乎是使第 5.1.2.3.6 节变得可理解的唯一读物,因为从直觉上讲,我们期望仅使用标准描述的工具的 C 程序的“可观察行为”大致如下:
  • 以程序本身外部可见的方式更改内存;
  • 更改文件的内容(根据定义,文件内容在外部可见
    程序本身);和
  • 影响与交互设备的交互

  • 这似乎是 § 5.1.2.3.6 试图达到的本质。

    编辑

    评论中似乎有一些小争议,显然集中在退出状态可以在寄存器中传递的想法,并且寄存器不能是对象。这个反对意见(没有双关语)是微不足道的:
  • 可以使用 register 声明对象存储类说明符,此类对象可以由左值指定;
  • 内存映射寄存器在嵌入式编程中相当普遍,它提供了与寄存器可以是对象、可以具有地址以及可以由左值指定的任何示例一样清晰的演示。实际上,内存映射寄存器是 volatile 最常见的用途之一。 - 合格的类型;
  • mmap()表明即使文件内容有时也可以有地址并且是对象。

  • 一般来说,认为对象只能驻留在核心内存或 DRAM 芯片组中的位置,或者认为“地址”只能指代的位置,或任何其他人通常称为“内存”或“内存”。任何能够存储值的执行环境组件,包括寄存器,都可能是一个对象,可能有一个地址,可能由一个左值指定,这就是为什么标准中“对象”的定义是故意用如此宽泛的术语进行类型转换。

    此外,诸如第 5.3.2.1.9 节之类的部分在“实际对象的值”和“抽象语义指定的[值]”之间进行了一些区分,表明实际对象是存在于执行中的真实事物环境与抽象机器不同,并且是规范确实密切关注的事物,正如第 3.15 节中“对象”的定义所明确的那样。坚持这样一种立场似乎站不住脚,即标准本身只关注这样的实际对象,直到并且仅直到调用标准库函数的时候,在这一点上,所有这些问题都消失了,这些事情突然变成了“在 C 之外”。

    关于c - 退出状态是可观察的行为吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53815997/

    相关文章:

    scala - 如何在 Scala JS build.sbt 中设置主类?

    c - 文件放在哪里以及如何编译和运行它?

    c - (c) 表达式必须是可修改的左值

    c++ - 微型过滤器从用户模式应用程序接收恒定值

    c++ - 为什么 gcc 会在全局命名空间中隐藏重载函数?

    actionscript-3 - 静态主类 - AS3

    c - 如何将char值转换为二进制并分别显示每一位?

    c++ - 为什么这些具有外部链接的名称不表示同一实体?

    c++ - 自动和友元函数的返回类型匹配

    scala - 主方法中的Scala App val初始化