CSAPP中有意思的代码集锦-001-内存引用bug

一、 内存引用Bug

#include 

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;
}
runing till fun(5)

由上图我们可以看到,s.d的值被改变了,同时,本应该i=5的地方莫名其妙地出现了s.d的值。
并且,当运行到fun(6)时,我们得到内存访问错误的提示。


fun(6) err

二、Bug产生的原因

通过分析,上述Bug一共导致了两个不寻常的现象。

  1. 结构体中的值被改变。
  2. 内存访问错误。

Bug产生的原因与数据在内存中的分布和内存访问的方式有关。在C和C++中,地址的访问不会做边界检查,因此,当访问越界,我们不会得到编译器的警告。以下是一个结构体内存分布示例:

explanation of fun

图片来源csapp第三版
从图中我们可以看到,该结构体一共被分配了7个块,每个块4个字节。当i=0,1时,我们得到的是a[0]和a[1]的正常访问结果;当i=2,3时,我们访问到的是s.d的两块4字节内存块,所以当我们改变值时,改变的其实是s.d地址下的数据;之后,当访问到i=6时,我们修改了结构体内存中关于程序状态的某些数据,这些修改导致了某些问题使程序无法继续执行下去。于是我们得到了上图测试中的那个error。
综上所述,内存引用bug的原因算是找到了。

你可能感兴趣的:(CSAPP中有意思的代码集锦-001-内存引用bug)