第三章 機器的程式級表示(下)
資料傳送:
當過程P呼叫過程Q時,P的程式碼必須首先把引數複製到適當的暫存器中。類似的,當Q返回到P時,P的程式碼可以訪問暫存器中的返回值;
每個過程呼叫在棧中都有它自己的私有空間,因此,多個未完成呼叫的區域性變數不會相互影響。當過程被呼叫時分配區域性儲存,當返回時釋放儲存;
陣列的分配和訪問:
對於資料型別T和整型常數N,陣列表現形式如下:T A[N]。它表示在記憶體中分配一個L*N位元組的連線區域,這裡L是資料型別T的位元組大小。當然,A也可以用來作為指向陣列開頭的指標。如:
char A[12];
char *B[8];
宣告一個數組 T D[R][C],它的陣列元素D[i][j]的記憶體地址為: D地址 + L( i * C + j )
比如,int A[5][3],其中,C的值即列數3,L即int型別的位元組長度4,所以,資料元素A[i][j] 的記憶體地址為:A資料地址 + 4*(3*i+j)
定長陣列:當程式要用一個常數作為一個數組的維度或者緩衝區的大小時,最好通過#define宣告這個常數與一個名字聯絡起來,然後在後面一直使用這個名字來替代常數的值。這樣,如果需要修改這個值,直接改這個#define宣告就好了。如
#define N 16;
typedef int fix_matrix[N][N];
變長陣列:陣列在被分配時才計算出來陣列長度大小,一般都是使用malloc這種函式來為這些陣列分配儲存空間;如,int A[expr1][expr2],如果A陣列作為一個函式引數,那麼,在呼叫函式,遇到這個宣告的時候,通過對錶達式exp1和exp2求值來確定陣列的維度;
異質的資料結構:
使用struct來宣告,將可能多個不同型別的物件聚合到一個物件中。如:
緩衝區溢位:C對於陣列引用不進行任何邊界檢查,而且區域性變數和狀態資訊都是存放在棧中。這兩種情況結合到一起就能導致嚴重的程式錯誤,對越界的陣列元素的寫操作會破壞儲存在棧中的狀態資訊。通常,當棧中分配某個字元陣列來儲存一個字串,但是字串長度超出了為陣列分配的空間。
對抗緩衝區溢位攻擊機制:
1.棧隨機化
2.棧破壞檢測;
3.限制可執行程式碼區域;
上面的方法都是由編譯器或作業系統完成的,無需程式設計師主動關心。