壹、記憶體視窗簡易操作
以 malloc / new 而言,無法使用監看式方式查看記憶體內含值,此時必須藉助記憶體視窗監看。考慮以下程式碼
#include <stdio.h> #define N 10 int main() { int i, arr[N]; for(i=0; i!=N; ++i) arr[i]=100+i; for(i=0; i!=N; ++i) /* break point here */ printf("arr[%d]=%d\n", i, arr[i]); return 0; /* break point here */ }
雖可以監看式觀查靜態陣列 arry,但此處以「記憶體」方式監看。注意上面的結果,arr[0] = 100,arr[1]=101,依此類推。
1. 按下 F5 (偵錯執行)後,再按「偵錯」->「視窗」->「記憶體」->「記憶體1」
2. 完成後將跳出如下視窗,先將焦點放到「位址」裡
3. 輸入 arr (注意,此處為欲監看之記憶體位址)
4. 最後會跳到 arr 之位址上去
在此需注意,arr 宣告為整數陣列,在我手邊之環境,sizeof(int) = 4,且為 little endian,下述之反白部份即為 &arr[0] 之內含值,也代表著 arr[0] 內含值為 0x00000064,換成 10 進制即為 100。
5. 調整資料顯示方式
也由於是 little endian ,在這例子而言,為 4 bytes 看作一筆資料,故做適當調整。於記憶體視窗上,按「右鍵」,選擇「4個位元組整數」。
顯示結果如下,變成 4 個位元組做一次顯示
甚至若覺得看 16 進位麻煩,可再次按右鍵,勾選「帶正負號顯示」,即可變成有號數方式顯示。
顯示結果如下。
若覺得想要固定每行有幾筆資料,在「資料行」那裡做選擇。如下所示。
個人較為偏好資料行使用「自動」,因在調整視窗大小時,每行可顯示之資料筆數會隨之調整。
6. 更改記憶體內含值
在做更改記憶體內含值時,必須以十六進位方式顯示方可更改。
假設欲更改 arr[0] 與 arr[5] 內含值,先在「位址」裡輸入 arr (或 &arr[0]),按 Enter 後,將游標放在最前面 bit 上
開始輸入欲更改之內容,假設欲改成 0x00009999,直接輸入 00009999 即可。注意,要修改時,不能選取整個數值,必須讓游標一次只選一個數字,輸入過去即可。
改完之後,繼續在記憶體「位址」上,輸入 &arr[5],完成按 Enter
有時按完 Enter 後,「位址」數字會跳動,代表即是 &arr[5] 之位址值。繼續再次輸入 00009999。
接下來,改完後記得按一下「自動重新評估」,以確保能順利改過。
按完之後,那些剛被改過變紅色的值,應會變回黑色,代表已順利改過。完成後,再按一次 F5,切到 console 視窗裡面去,可看到 arr[0] 與 arr[5] 已被改為39321,即 16 進位之 0x00009999
貮、 監看動態記憶體
考慮以下程式碼
#include <stdio.h> #include <stdlib.h> #define N 10 int main() { int i, *ptr; ptr = (int*)malloc(sizeof(int)*N); for(i=0; i!=N; ++i) ptr[i]=i+100; free(ptr); /* break point here */ return 0; }
如之前所說,這段程式碼在一般之監看式裡只看得到指標,看不到配置出來之記憶體位址。但用記憶體視窗方式會較好觀查。
在記憶體視窗裡,直接輸入 ptr
上面便把 ptr[0]~ptr[9] 所有內容都顯示出來,若用監看式要自己 keyin 的話,則必須要 ptr[0], ptr[1]... ptr[9], 一筆一筆慢慢輸入,沒太大效率。
但若是分配二維動態記憶體的話 (假設欲配置 ptr[3][4]),再考慮以下程式碼
#include <stdio.h> #include <stdlib.h> #define X 3 #define Y 4 int main() { int i, j; int **ptr; // Allocate ptr = (int**)malloc(sizeof(int*)*X); for(i=0; i!=X; ++i) ptr[i] = (int*)malloc(sizeof(int)*Y); // Set Value for(i=0; i!=X; ++i) for(j=0; j!=Y; ++j) ptr[i][j] = i*Y+j; // Release for(i=0; i!=X; ++i) /* break point here */ free(ptr[i]); free(ptr); return 0; }
一樣於記憶體「位址」裡面,輸入 ptr ,裡面內容卻如下所示
這是因為,ptr 先配置了 3 個指標出來,故只輸入 ptr,只會查到 ptr[i] 之三個 address。
若要繼續查 ptr[0] 裡面的 ptr[0][0]~ptr[0][3],在上圖看來,位址是 00395dc8,
但不用輸入那個 magic number,直接輸入 ptr[0] 即可
一樣,要查 ptr[1][0]~ptr[1][3],直接輸入 ptr[1] 即可。
這樣查,很費時間,因配置出來的記憶體內含值並不連續。
參、 較佳之動態配置策略
在上一個例子裡面用 malloc 去配置一個二維之動態陣列 ptr[3][4],在記憶體裡面,元素值不一定是連續之狀態,因所配置的先是 3 個指標,再用這 3 個指標去配置 4 個整數陣列。這種可能發生不連續配置之問題,稱作 記憶體碎片化 。有一說未查證過,記憶體碎片化目前大多之作業系統都可處理掉, Coder 可不必考慮這問題,但我較乃把這問題考慮進去,反正也只是一點程式寫作上之技巧而已。
假設欲配置 int ptr[X][Y],在配置的過程中,
(1) 先直接配置一維之 int trunk[X*Y]
(2) ptr 再配置一維之 (int*) ptr[X]
(3) ptr[0] = trunk[0]
(4) ptr[i] = trunk[i] + Y * sizeof(int)
說得似乎很抽象,看個程式碼想一下很快理解。
#include <stdio.h> #include <stdlib.h> #define X 3 #define Y 4 int main() { int i, j; int **ptr; int *trunk; // Allocate trunk = (int*)malloc(sizeof(int)*X*Y); ptr = (int**)malloc(sizeof(int*)*X); for(i=0; i!=X; ++i) { ptr[i] = trunk; trunk+=Y; } // Set Value for(i=0; i!=X; ++i) for(j=0; j!=Y; ++j) ptr[i][j] = i*Y+j; // Release free(*ptr); /* break point here */ free(ptr); return 0; }
好了之後,這次再次於記憶體視窗之位址裡面,輸入 &ptr[0][0] (或輸入 ptr[0] ),這次發現所配出來的記憶體都是連續的。
一樣的方式,也可用在三維配置上,於此不再示範。
留言列表