c - 是否在其绑定(bind)的未定义行为之外访问全局数组?

标签 c undefined-behavior

我今天刚在类考试---阅读C代码和输入,要求的答案是程序实际运行时屏幕上会出现什么。申报问题之一a[4][4]作为全局变量并在该程序的某个点,它尝试访问 a[27][27] ,所以我回答了类似“Accessing an array outside its bounds is an undefined behavior”的问题,但老师说的是a[27][27]的值为 0 .

后来,我尝试了some code检查“所有未初始化的 golbal 变量都设置为 0”是否为真。好吧,这似乎是真的。

那么现在我的问题是:

  • 似乎一些额外的内存已被清除并保留用于代码运行。保留多少内存?为什么编译器会保留比应有的更多的内存,它有什么用?
  • 威尔 a[27][27]0适用于所有环境?

编辑:

在该代码中,a[4][4]是声明的唯一 全局变量,main() 中还有一些局部变量.

我试过了 that code再次在 DevC++ 中。都是0 .但在 VSE 中情况并非如此,其中大多数值是 0但正如 Vyktor 指出的那样,有些具有随机值。

最佳答案

你是对的:这是未定义的行为,你不能指望它总是产生 0

至于为什么在这种情况下您会看到零:现代操作系统以相对粗粒度的 block (称为页面)为进程分配内存,这些 block 比单个变量大得多(在 x86 上至少为 4KB)。当您只有一个全局变量时,它将位于页面的某个位置。假设 a 的类型为 int[][] 并且 int 在您的系统上是四个字节,a[27][27 ] 将位于 a 开头约 500 字节处。所以只要 a 靠近页面的开头,访问 a[27][27] 就会得到实际内存的支持,读取它不会导致页面故障/访问冲突。

当然,你不能指望这个。例如,如果 a 前面有将近 4KB 的其他全局变量,那么 a[27][27] 将不会得到内存支持,当您执行以下操作时,您的进程将崩溃尝试阅读它。

即使进程没有崩溃,您也不能指望得到值 0。如果您在现代多用户操作系统上有一个非常简单的程序,除了分配这个变量并打印那个值之外什么都不做,您可能会看到 0。操作系统在将内存移交给进程时将内存内容设置为某个良性值(通常全为零),以便来自一个进程或用户的敏感数据不会泄漏到另一个。

但是,并不能保证您读取的任意内存将为零。您可以在内存未在分配时初始化的平台上运行您的程序,并且您会看到上次使用时碰巧存在的任何值。

此外,如果 a 后跟足够多的其他初始化为非零值的全局变量,那么访问 a[27][27] 将显示任何值恰好在那里。

关于c - 是否在其绑定(bind)的未定义行为之外访问全局数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26426910/

相关文章:

c++ - 清除已经为空的 vector 会导致未定义的行为吗?

c - 使用 UB 打印的宏功能

c++ - 未定义的行为和顺序点

c - 海合会: "warning: assignment from incompatible pointer type"

c - 静态变量的奇怪情况仅出现在 gcc 的调试版本中

c - strcat 未按预期运行

c - 未初始化的 C 结构字段

c - 在 C 中实现 strcpy 时出现问题

c - 添加两个短号码时

c++ - 混合 C 和 C++ 代码的静态分析怪异符号行为