代码之家  ›  专栏  ›  技术社区  ›  sharptooth

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

  •  0
  • sharptooth  · 技术社区  · 15 年前

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

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

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

    9 回复  |  直到 15 年前
        1
  •  3
  •   Thomas Padron-McCarthy    15 年前

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

    编辑:

    未指明

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

    这在执行之间也可能有所不同。正如标准所说: “一个抽象机器的实例可以对一个给定的程序和一个给定的输入有多个可能的执行序列。” 未定义 行为,任何事情都有可能发生:计算机可能爆炸,重新格式化磁盘,或者其他什么。如果行为未指定,则不允许计算机爆炸。

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

        2
  •  5
  •   Dave D    15 年前

    如果它是未定义的行为,那么就其本质而言,将要发生的事情是未定义的,你不能依赖它是相同的 情况。

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

        3
  •  3
  •   AnT stands with Russia    15 年前

    未指定和未定义的行为不能保证在单独的 一个已经编译的程序。单凭这一点,就已经使这两个国家之间的一致性概念分离了 编译

    另外,可能值得补充的是,未定义的行为可以通过阻止程序编译而在编译阶段表现出来。

        4
  •  2
  •   anon anon    15 年前

    在计算机上编译同一程序 中具有相同设置的相同编译器 同样的环境?

    对。

    换句话说,如果我取消引用 以及实现格式 在这种情况下开车是不是意味着 节目结束后也会这样 是否重新编译?

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

        5
  •  1
  •   PeterK    15 年前

        6
  •  1
  •   Martin Konecny    15 年前

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

        7
  •  1
  •   Blair Holloway    15 年前

    值得注意的是 特定行为 在C++编译器中,即使在今天,也不是100%个相同的编译器。有鉴于此,期望未指定或未定义的行为是编译器不可知的是不合理的。如果你坚持标准,你就有机会写出可移植的代码。

        8
  •  1
  •   mouviciel    15 年前

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

        9
  •  1
  •   Max Lybbert    15 年前

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

    在许多情况下,未定义的行为被实现为没有检查的东西。如果有操作系统,并且它注意到发生了一些不符合犹太教义的事情,那么行为就由操作系统决定。

    new delete 但操作系统相信你拥有它。有时会发生崩溃,有时会损坏程序中其他地方的内存,有时会逃之夭夭(例如,如果内存没有被发回)。

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

    删除