CSAPP中有意思的代碼集錦-001

一、 內存引用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;
}

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的原因算是找到了。

如果你喜歡我的內容,歡迎打賞哦~
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章