c - 为什么这个内存引用段错误?

标签 c memory-management

double fun(int i)
{
 volatile double d[1] = {3.14};
 volatile long int a[2];
 a[i] = 1073741824;
 return d[0];
}

有趣(0) ➙ 3.14

有趣(1) ➙ 3.14

有趣(2) ➙ 3.1399998664856

有趣(3) ➙ 2.00000061035156

fun(4) ➙ 3.14,然后出现段错误

有人可以向我解释一下这个例子中发生了什么以及为什么在调用 func(2) 时没有出现段错误吗? 为什么返回值不总是 3.14?

最佳答案

您声明一个包含 2 个条目的数组:

volatile long int a[2];

然后您可以使用索引访问该数组:

a[i] = 1073741824;

由于 C 中的数组索引从 0 开始,任何大于 1 的索引都会产生未定义的行为。

在您的程序中,您正在使用索引 i=2i=3i=4 调用函数。

这些函数调用中的每一个都会独立地产生未定义的行为。

未定义的行为意味着任何事情都可能发生。

您仅在 fun(4) 上遇到段错误这一事实纯属巧合。

<小时/>

补充:

免责声明:以下分析并不意味着每个平台甚至每次执行都会出现相同的行为;这只是为了解释观察到的“奇怪”返回值。

  • 1073741824 的 4 字节十六进制值为 0x40000000
  • 3.14 的 8 字节十六进制值为 0x40091EB851EB851F(符合 IEEE 754)
  • 通过将 0x40000000 写入 a[2],您已覆盖 d[0] 的 8 字节值中的 4 个最低有效字节 code> (不会导致段错误),从而将其从 0x40091EB851EB851F 更改为 0x40091EB840000000,它代表 3.1399998664856< 的 (IEEE 754) 浮点值
  • 通过将 0x40000000 写入 a[3],您已覆盖 d[0] 的 8 字节值中的 4 个最高有效字节 code> (不会导致段错误),从而将其从 0x40091EB851EB851F 更改为 0x4000000051EB851F,它代表 2.0000006103516< 的 (IEEE 754) 浮点值

关于c - 为什么这个内存引用段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35148530/

相关文章:

c - 获取文件 C 中行数的最佳方法

java - Swig 如何定义一个类型映射,将 C 类型定义的 boolean 值转换为 java boolean 值

c - EXTI_Init 函数中访问越界错误

Java mmap 在 Android 上失败并显示 "mmap failed: ENOMEM (Out of memory)"

optimization - 释放已分配的内存

c - 在内核重启后保留文件

c - 引用 C 中不带前导下划线的外部符号

iphone - iOS 应用程序崩溃偶尔崩溃 - 在屏幕显示或向下滚动时

objective-c - timeIntervalSinceDate 给出 exc_bad_access 或 autorelease 错误

memory - 为什么每个进程都需要自己的页表?