程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 從匯編的眼光看C++(之delete內存洩露)

從匯編的眼光看C++(之delete內存洩露)

編輯:C++入門知識

 

【 聲明:版權所有,歡迎轉載,請勿用於商業用途。  聯系信箱:feixiaoxing @163.com】

 

 

 

 

    有過C語言編程的朋友大多知道,如果在malloc內存之後不及時free掉內存,那麼很有可能會造成內存洩露的。那麼在C++上面,是不是也存在這樣的問題呢?結果是C++上面同樣也存在內存洩露的危險。這個危險就是如果new後面不能delete的話,也會造成內存的洩露。還有不清楚的朋友可以看看下面的示例:

 

 

class test 

    int data; 

public: 

    test(int value):data(value) {} 

    ~test() {}; 

}; 

 

void process() 

    test* t = new test(0); 

 

    if(/* some errors happens */) 

    { 

        return; 

    } 

 

    delete t; 

    return; 

class test

{

       int data;

public:

       test(int value):data(value) {}

       ~test() {};

};

 

void process()

{

       test* t = new test(0);

 

       if(/* some errors happens */)

       {

              return;

       }

 

       delete t;

       return;

}    上面的代碼在一定程度上說明了問題。其實上面這段代碼在函數返回的時候已經考慮到了內存刪除的問題,但是關鍵是如果在error發生的時候,沒有及時處理的話也會造成內存洩露的。那麼有沒有什麼好的方法呢?大家可以看看C++有沒有什麼性質可以保證函數在結束的時候可以自動完成資源的釋放。對,那就是析構函數。所以,一般的話我們可以添加一個額外的類定義。

 

 

class auto_point 

    test* t; 

public: 

    auto_point(test* p) : t(p) {} 

    ~auto_point() { if(t) delete t;} 

}; 

class auto_point

{

       test* t;

public:

       auto_point(test* p) : t(p) {}

       ~auto_point() { if(t) delete t;}

};    但是,原來我們的好多操作都是按照指針進行的,那麼怎麼把類轉變成指針呢?那就只有使用算術符重載了。

 

 

class auto_point 

    test* t; 

public:  

    auto_point(test* p) : t(p) {} 

    ~auto_point() { if(t) delete t;} 

    test* operator->() { return t;} 

    const test& operator* () {return *t;} 

}; 

class auto_point

{

       test* t;

public:

       auto_point(test* p) : t(p) {}

       ~auto_point() { if(t) delete t;}

       test* operator->() { return t;}

       const test& operator* () {return *t;}

};

    那麼有了這樣的一個定義之後,我們應該怎麼使用呢?大家可以看看下面的函數調用:

 

 

22:       auto_point p(new test(0)); 

004010AD   push        4 

004010AF   call        operator new (00401300) 

004010B4   add         esp,4 

004010B7   mov         dword ptr [ebp-18h],eax 

004010BA   mov         dword ptr [ebp-4],0 

004010C1   cmp         dword ptr [ebp-18h],0 

004010C5   je          process+56h (004010d6) 

004010C7   push        0 

004010C9   mov         ecx,dword ptr [ebp-18h] 

004010CC   call        @ILT+80(test::test) (00401055) 

004010D1   mov         dword ptr [ebp-1Ch],eax 

004010D4   jmp         process+5Dh (004010dd) 

004010D6   mov         dword ptr [ebp-1Ch],0 

004010DD   mov         eax,dword ptr [ebp-1Ch] 

004010E0   mov         dword ptr [ebp-14h],eax 

004010E3   mov         dword ptr [ebp-4],0FFFFFFFFh 

004010EA   mov         ecx,dword ptr [ebp-14h] 

004010ED   push        ecx 

004010EE   lea         ecx,[ebp-10h] 

004010F1   call        @ILT+65(auto_point::auto_point) (00401046) 

004010F6   mov         dword ptr [ebp-4],1 

23:       if(1/* some errors happens */) 

004010FD   mov         edx,1 

00401102   test        edx,edx 

00401104   je          process+97h (00401117) 

24:       { 

25:           return; 

00401106   mov         dword ptr [ebp-4],0FFFFFFFFh 

0040110D   lea         ecx,[ebp-10h] 

00401110   call        @ILT+75(auto_point::~auto_point) (00401050) 

00401115   jmp         process+0A6h (00401126) 

26:       } 

27: 

28:       return; 

00401117   mov         dword ptr [ebp-4],0FFFFFFFFh 

0040111E   lea         ecx,[ebp-10h] 

00401121   call        @ILT+75(auto_point::~auto_point) (00401050) 

29:   } 

22:       auto_point p(new test(0));

004010AD   push        4

004010AF   call        operator new (00401300)

004010B4   add         esp,4

004010B7   mov         dword ptr [ebp-18h],eax

004010BA   mov         dword ptr [ebp-4],0

004010C1   cmp         dword ptr [ebp-18h],0

004010C5   je          process+56h (004010d6)

004010C7   push        0

004010C9   mov         ecx,dword ptr [ebp-18h]

004010CC   call        @ILT+80(test::test) (00401055)

004010D1   mov         dword ptr [ebp-1Ch],eax

004010D4   jmp         process+5Dh (004010dd)

004010D6   mov         dword ptr [ebp-1Ch],0

004010DD   mov         eax,dword ptr [ebp-1Ch]

004010E0   mov         dword ptr [ebp-14h],eax

004010E3   mov         dword ptr [ebp-4],0FFFFFFFFh

004010EA   mov         ecx,dword ptr [ebp-14h]

004010ED   push        ecx

004010EE   lea         ecx,[ebp-10h]

004010F1   call        @ILT+65(auto_point::auto_point) (00401046)

004010F6   mov         dword ptr [ebp-4],1

23:       if(1/* some errors happens */)

004010FD   mov         edx,1

00401102   test        edx,edx

00401104   je          process+97h (00401117)

24:       {

25:           return;

00401106   mov         dword ptr [ebp-4],0FFFFFFFFh

0040110D   lea         ecx,[ebp-10h]

00401110   call        @ILT+75(auto_point::~auto_point) (00401050)

00401115   jmp         process+0A6h (00401126)

26:       }

27:

28:       return;

00401117   mov         dword ptr [ebp-4],0FFFFFFFFh

0040111E   lea         ecx,[ebp-10h]

00401121   call        @ILT+75(auto_point::~auto_point) (00401050)

29:   }

    大家可以從上面的代碼看得很清楚,不管代碼在什麼時候退出,函數都會利用類的基本特性,自動調用類的析構函數,那麼進而內存就會得到釋放,不會發生內存洩露的問題。但是我們發現上面的解決方案也有不足的地方,就是每一個類都需要額外定義一個額外的定義類。那麼有沒有什麼辦法解決這一問題呢?那就是模板了。

 

 

template <typename type> 

class auto_point 

    type* t; 

public: 

    auto_point(type* p) : t(p) {} 

    ~auto_point() { if(t) delete t;} 

    test* operator->() { return t;} 

    const test& operator* () {return *t;} 

}; 

template <typename type>

class auto_point

{

       type* t;

public:

       auto_point(type* p) : t(p) {}

       ~auto_point() { if(t) delete t;}

       test* operator->() { return t;}

       const test& operator* () {return *t;}

};    如果我們的類型不是特定的,那麼我們只需要在使用的時候按照特定的類型輸入即可

w Roman"'>)嘗試編寫一個二分法的泛型處理函數?

 

    (3)嘗試編寫一個quick_sort的泛型函數,可能考慮的因素需要多一些?不過也可以嘗試一下哦。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved