超出数组最大索引的未定义行为
Undefined behavior beyond the max index of an array
情况:
我正在参加速成课程以熟悉 C,我注意到本课程的作者可以打印超出数组索引的数组值,并确信该值将是 0
每次。
下面速成班的代码:
int arrayVar[] = {45, 67, 34, 23};
printf("This array index value is %d", arrayVar[4]);
代码输出:
This array index value is 0
根据我的经验,在 C 的 tinkering/testing 期间,一旦超出数组的最大索引,就会进入 未定义行为 领域,其中 任何事情 都可能发生,所以他怎么能如此自信(而且正确)每次都看到 0
值?
如果我打印超出数组最大索引的值,我会看到 "random" 个值(或者,留在内存中的值,对吧?)。
为什么我的体验与我在本课程中看到的不同?这只是C标准的不同吗?或者这是否表明编译器存在差异?或者两者兼而有之?
环境信息:我使用的是 C11 标准,并且我使用的编译器(我很确定)默认带有 ubuntu,位于 /usr/bin/cc
.
编辑:对于任何有兴趣了解我所看到的内容的人,这里有一个 link 课程(系统可能会提示您登录 Udemy) : https://www.udemy.com/c-fast-crash-course-introduction/learn/lecture/12868540#questions
课程作者有误
就这么简单
- 未定义不代表随机。在许多情况下,undefined 通常会导致一些默认行为,因此可能会在很长一段时间内被忽视。内存通常用零初始化,因此访问未初始化的内存通常会产生零。这就是为什么一些内存调试器库会用不常见的值(例如 0xDEADBEEF)填充分配的内存,这些值更有可能触发问题。
- 内存分配很重要。底层库需要跟踪分配的和空闲的,有不同类型的分配(堆栈与堆、数据段、BSS 等)。图书馆可能有分配某些小对象等的优化策略 - 你不会调用 OS 来分配 16 个字节,但是 "the situation is complicated"。当您分配 16 个字节时,您的 C 库可能会要求几兆字节(如果它之前没有这样做),内核假装它将所有这些内存提供给应用程序(假设经常没有使用所有这些内存)并且该库然后用您的 16 字节 加上 一些内存管理开销削减了一个块。通常与 8 字节边界对齐,因为出于多种原因,在字节级别微管理内存不是一个好主意。所以下一个整数可能已经分配并清除了这个兆字节以供将来使用。
(虽然在这种特殊情况下,数组应该在数据部分并且从未分配过,但想法是相似的 - 接下来可能有一些静态变量恰好为零。您可能想查看二进制文件数据段的转储布局。)
情况:
我正在参加速成课程以熟悉 C,我注意到本课程的作者可以打印超出数组索引的数组值,并确信该值将是 0
每次。
下面速成班的代码:
int arrayVar[] = {45, 67, 34, 23};
printf("This array index value is %d", arrayVar[4]);
代码输出:
This array index value is 0
根据我的经验,在 C 的 tinkering/testing 期间,一旦超出数组的最大索引,就会进入 未定义行为 领域,其中 任何事情 都可能发生,所以他怎么能如此自信(而且正确)每次都看到 0
值?
如果我打印超出数组最大索引的值,我会看到 "random" 个值(或者,留在内存中的值,对吧?)。
为什么我的体验与我在本课程中看到的不同?这只是C标准的不同吗?或者这是否表明编译器存在差异?或者两者兼而有之?
环境信息:我使用的是 C11 标准,并且我使用的编译器(我很确定)默认带有 ubuntu,位于 /usr/bin/cc
.
编辑:对于任何有兴趣了解我所看到的内容的人,这里有一个 link 课程(系统可能会提示您登录 Udemy) : https://www.udemy.com/c-fast-crash-course-introduction/learn/lecture/12868540#questions
课程作者有误
就这么简单
- 未定义不代表随机。在许多情况下,undefined 通常会导致一些默认行为,因此可能会在很长一段时间内被忽视。内存通常用零初始化,因此访问未初始化的内存通常会产生零。这就是为什么一些内存调试器库会用不常见的值(例如 0xDEADBEEF)填充分配的内存,这些值更有可能触发问题。
- 内存分配很重要。底层库需要跟踪分配的和空闲的,有不同类型的分配(堆栈与堆、数据段、BSS 等)。图书馆可能有分配某些小对象等的优化策略 - 你不会调用 OS 来分配 16 个字节,但是 "the situation is complicated"。当您分配 16 个字节时,您的 C 库可能会要求几兆字节(如果它之前没有这样做),内核假装它将所有这些内存提供给应用程序(假设经常没有使用所有这些内存)并且该库然后用您的 16 字节 加上 一些内存管理开销削减了一个块。通常与 8 字节边界对齐,因为出于多种原因,在字节级别微管理内存不是一个好主意。所以下一个整数可能已经分配并清除了这个兆字节以供将来使用。 (虽然在这种特殊情况下,数组应该在数据部分并且从未分配过,但想法是相似的 - 接下来可能有一些静态变量恰好为零。您可能想查看二进制文件数据段的转储布局。)