一、 內存引用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的原因算是找到了。