一般在C語言中我們使用malloc和free進行記憶體配置設定和釋放,但是在C++中增加了一個新的
new和delete 操作來進行,按照C++的說法delete是釋放記憶體但是指針得到保留,防止記憶體
洩露,并且NEW和DELETE要成對出現。我們知道指針本生也是一個儲存在記憶體中某個位置的變量,
如果釋放了記憶體我們是否可以考慮為其中的值得到了删除,而指針自身可以再次指向其他的值?
而還有一點我們需要明白使用NEW配置設定的記憶體是HEAP而變量的指派是棧,
在OS中我們大概可以了解如下(32位系統為例),我這裡的共享是指線程是否共享:
4G
kernel --核心記憶體
3G text --代碼文本 共享
data --初始化的全局變量和靜态變量 共享
dss --未始化的全局變量和靜态變量 共享
棧 --級動态變量數組等 不共享
堆 --malloc 共享
0 共享庫 --庫檔案 mmap 映射 共享
可以看到棧和堆不是一個區域,并且棧始終是自我釋放的遵循後入先出原則
我們接下來用如下的小程式帶上GDB進行調試
8 #include
9 using namespace std;
10
11
12 int main(void)
13 {
14 int *p; //一個不初始化的指針,不能使用*p=一個INT數字,隻能賦予一個指針變量p=(init *)0x130000表示p指針指向130000位置
15 short *b = new short;
16 short *c = new short;
17
18 *b=0X128;
19
20 cout<<"noinit int address is :"<< p <<" "<<sizeof(*p)<<endl;
21 cout<<"short b address is :"<< b <<" "<<sizeof(*b)<<"\n";
22 cout<<"short c address is :"<< c <<" "<<sizeof(*c)<<endl;
23 delete b; //成對出現
24 delete c;
25 //DELETE不釋放指針隻是釋放記憶體,那麼指針指向的記憶體可以用于其他用途
26 cout<<"init int address is :"<< b <<" "<<sizeof(*b)<<"\n";
27 cout<<"noinit dou address is :"<< c <<" "<<sizeof(*c)<<endl;
28
29 *b=0X256; //直接賦予值,指派成功
31 delete b; //不成對出現
32 *b=0X512; //便于觀察而已
33 delete b; //便于觀察,避免指針釋放
}
~ 如果我們在
23 delete b;
後去GDB *b的隻為0那麼說明delete起到了效果
gdb ./a.out
(gdb) b 23
Breakpoint 1 at 0x400a79: file pointer2.cpp, line 23.
(gdb) r
Breakpoint 1, main () at pointer2.cpp:23
23 delete b;
(gdb) p b
$1 = (short *) 0x602010
(gdb) x/2xh 0x602010
0x602010: 0x0128 0x0000
可以看到目前為0X0128資料在這個存儲2個位元組裡面我是也就是0x602010 0x602011
(gdb) n
24 delete c;
(gdb) x/2xh 0x602010
0x602010: 0x0000 0x0000
這裡跑完了delete b; 可以看到資料沒有了在記憶體中,繼續
繼續向下
29 *b=0X256;
30 delete b;
$3 = (short *) 0x602010
這裡跑完了 *b=0X256;但是指針位置沒有變化,也就是DELETE後指針得到了保留
繼續
(gdb) p *b
$4 = 598
0x602010: 0x0256 0x0000
可以看到資料沒有問題。繼續看看是否能DELETE
0x602010: 0x2020 0x0060
可以看到delete并沒有删除資料而已弄了一些垃圾資料進來。
其實這個程式直接跑會報錯
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000000f1f010 ***
Aborted (core dumped)
用GDB隻是為了找到原因
是以我們必須new和delete 成對使用,否者結果是不确定的,對空指針delete是安全的
delete後指針是得到了保留的沒有問題,如果是動态數組将不能使用sizeof來确定他的長度
指針我感覺是使用的棧,同時在函數結束時自我釋放。
附帶關于GDB的記憶體檢視
轉自:http://www.cnblogs.com/super119/archive/2011/03/26/1996125.html
格式: x /nfu
說明
x 是 examine 的縮寫
n表示要顯示的記憶體單元的個數
f表示顯示方式, 可取如下值
x 按十六進制格式顯示變量。
d 按十進制格式顯示變量。
u 按十進制格式顯示無符号整型。
o 按八進制格式顯示變量。
t 按二進制格式顯示變量。
a 按十六進制格式顯示變量。
i 指令位址格式
c 按字元格式顯示變量。
f 按浮點數格式顯示變量。
u表示一個位址單元的長度
b表示單位元組,
h表示雙位元組,
w表示四位元組,
g表示八位元組
Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),
t(binary), f(float), a(address), i(instruction), c(char) and s(string).
Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes)
舉例
x/3xh buf
表示從記憶體位址buf讀取内容,
h表示以雙位元組為一個機關,
3表示三個機關,
x表示按十六進制顯示
</sizeof(*c)<<endl;
</sizeof(*b)<<"\n";
</sizeof(*p)<<endl;