【问题标题】:Is it undefined behavior to access an array out of bounds if I know what data is at the accessed adress?如果我知道访问的地址上有什么数据,那么越界访问数组是否是未定义的行为?
【发布时间】:2023-01-17 16:31:44
【问题描述】:

想象一下下面的定义。

struct X {
    double a[8] {0.0};
    double b[8] {0.0};
}

int main() {
    X x;
    x.a[10] = 1.0;
}

当我访问x.a[10]时,程序的行为是否未定义?

【问题讨论】:

  • 请注意,术语未定义的行为(UB) 由 C++ 标准使用。如果根据 C++ 标准,存在 UB,则程序的行为可能由机器代码级别的实现很好地定义(这可能是您的情况)。

标签: c++ stack undefined-behavior


【解决方案1】:

是的,这是未定义的行为,但不仅仅是因为编译可能会改变 X 的内存布局。

这是未定义的行为,因为标准是这么说的。结果编译器可以做任何使用这段代码:编译器可以完全放弃赋值,可以将1.0赋值给全部16 元素,可以使程序崩溃、格式化硬盘等。

【讨论】:

    【解决方案2】:

    是的。这是未定义的行为。因为编译器可以在ab 之间插入一些填充。 Il 也可以在b 之后插入一些填充。 您唯一可以确定的是a 之前不会有任何填充。

    The Lost Art of Structure Packing 中提供了一个有趣且非常详细的描述。

    【讨论】:

      【解决方案3】:

      它是根据 g++/clang++ 内置的“未定义行为消毒剂”

      runtime error: index 10 out of bounds for type 'double [8]'
      

      Demo

      注意在演示中,检查器的调用发生在-fsanitize=undefined。我们有很棒的工具,让我们使用它们吧。

      另请注意,如果您启用内存检查器,即-fsanitize=address,则不会发出警告。也就是说,“仅仅因为它不会导致运行时内存问题并不意味着它不是 UB”。

      【讨论】:

        【解决方案4】:

        你的错误前提是越界访问将被定义,那么它当然是......不是未定义的。但事实并非如此。

        您假设这两个数组彼此相邻地存储在相邻的内存中,并且指针算法也可以超出数组的范围。第一个通常不正确,第二个总是错误的。

        指针算术仅在数组范围内定义。

        您的代码具有未定义的行为。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-11-16
          • 2021-05-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-21
          • 2021-11-29
          相关资源
          最近更新 更多