關於C++ delete 來釋放new分配的記憶體
一般在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;
(gdb) n
30 delete b;
(gdb) p b
$3 = (short *) 0x602010
這裡跑完了 *b=0X256;但是指標位置沒有變化,也就是DELETE後指標得到了保留
繼續
(gdb) p *b
$4 = 598
(gdb) x/2xh 0x602010
0x602010: 0x0256 0x0000
可以看到資料沒有問題。繼續看看是否能DELETE
(gdb) n
(gdb) x/2xh 0x602010
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(*c)<<endl;
</sizeof(*b)<<"\n";
</sizeof(*p)<<endl;
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;
(gdb) n
30 delete b;
(gdb) p b
$3 = (short *) 0x602010
這裡跑完了 *b=0X256;但是指標位置沒有變化,也就是DELETE後指標得到了保留
繼續
(gdb) p *b
$4 = 598
(gdb) x/2xh 0x602010
0x602010: 0x0256 0x0000
可以看到資料沒有問題。繼續看看是否能DELETE
(gdb) n
(gdb) x/2xh 0x602010
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(*c)<<endl;
</sizeof(*b)<<"\n";
</sizeof(*p)<<endl;
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2089546/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- new、delete、記憶體分配 的底層原理delete記憶體
- C/C++記憶體分配以及釋放C++記憶體
- C++ 記憶體分配(new,operator new)詳解C++記憶體
- 【C++】C++ 記憶體分配(new,operator new)詳解C++記憶體
- 記憶體(new delete )記憶體delete
- 記憶體動態分配與釋放,malloc和new區別記憶體
- C++動態記憶體管理——new/deleteC++記憶體delete
- C++記憶體管理:new / delete 和 cookieC++記憶體deleteCookie
- 記憶體的分配與釋放,記憶體洩漏記憶體
- vector 避免記憶體頻繁分配釋放與手動釋放vector記憶體記憶體
- [C++]記憶體分配C++記憶體
- C/C++使用malloc為結構體陣列分配記憶體(及free釋放記憶體)的三種方法C++結構體陣列記憶體
- 簡單分配和釋放記憶體指令碼[更新]記憶體指令碼
- 控制C++的記憶體分配C++記憶體
- C/C++——C和C++怎樣分配和釋放記憶體,區別是什麼?C++記憶體
- C++ vector 釋放記憶體的兩種方法C++記憶體
- 函式中的指標分配的記憶體怎麼釋放函式指標記憶體
- C++關於一個函式中new記憶體洩露的列子C++函式記憶體洩露
- 二維陣列的動態記憶體分配和釋放 (轉)陣列記憶體
- C++ 動態記憶體分配C++記憶體
- C++動態記憶體分配C++記憶體
- vector 的記憶體釋放記憶體
- C/C++記憶體釋放應注意的問題C++記憶體
- 記憶體分配詳解 malloc, new, HeapAlloc, VirtualAlloc,GlobalAlloc記憶體
- C語言記憶體管理,分配、使用、釋放以及安全性C語言記憶體
- Linux釋放記憶體及手動釋放Oracle共享記憶體段Linux記憶體Oracle
- XCode釋放記憶體XCode記憶體
- linux釋放記憶體Linux記憶體
- Java關於繼承中的轉型及其記憶體分配Java繼承記憶體
- C++ 指標動態記憶體分配C++指標記憶體
- 如何檢測記憶體洩漏——過載new和delete記憶體delete
- 正確釋放Vector的記憶體記憶體
- 誰建立誰銷燬,誰分配誰釋放——JNI呼叫時的記憶體管理記憶體
- mysql用於分配記憶體的引數MySql記憶體
- 軟體測試學習教程——過載new或delete來檢測記憶體洩漏delete記憶體
- Golang記憶體分配內建函式之new函式Golang記憶體函式
- 【OpenCV】有關記憶體釋放的一些問題OpenCV記憶體
- 關於c語言記憶體分配,malloc,free,和段錯誤,記憶體洩露C語言記憶體洩露