一、 内存引用Bug
#include <stdio.h>
typedef struct
{
int a[2];
double d;
} struct_t;
double fun(int i)
{
volatile struct_t s;
s.d = 3.14;
s.a[i] = 1073741824;
printf("%lf\n", s.d);
return s.d;
}
int main()
{
fun(0);
fun(1);
fun(2);
fun(3);
fun(4);
fun(5);
// fun(6);
return 0;
}
由上图我们可以看到,s.d的值被改变了,同时,本应该i=5的地方莫名其妙地出现了s.d的值。
并且,当运行到fun(6)时,我们得到内存访问错误的提示。
二、Bug产生的原因
通过分析,上述Bug一共导致了两个不寻常的现象。
- 结构体中的值被改变。
- 内存访问错误。
Bug产生的原因与数据在内存中的分布和内存访问的方式有关。在C和C++中,地址的访问不会做边界检查,因此,当访问越界,我们不会得到编译器的警告。以下是一个结构体内存分布示例:
图片来源csapp第三版
从图中我们可以看到,该结构体一共被分配了7个块,每个块4个字节。当i=0,1时,我们得到的是a[0]和a[1]的正常访问结果;当i=2,3时,我们访问到的是s.d的两块4字节内存块,所以当我们改变值时,改变的其实是s.d地址下的数据;之后,当访问到i=6时,我们修改了结构体内存中关于程序状态的某些数据,这些修改导致了某些问题使程序无法继续执行下去。于是我们得到了上图测试中的那个error。
综上所述,内存引用bug的原因算是找到了。