天天看點

關于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;

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;

繼續閱讀