C++關於一個函式中new記憶體洩露的列子
首先明白幾個基礎
1、函式按值傳遞和按值返回的時候都會呼叫複製建構函式
2、一般在函式體內定義的棧變數是不能返回其地址或者引用給主調函式的,因為在函式結束的時候這些棧變數將釋放
3、可以使用new的方式建立堆記憶體的方式,然後返回引用或者指標,因為new這種方式建立的堆記憶體並不隨函式的結束而結束,
而指標變數釋放但是指標本生的值已經返回。同時也可以按值放回,但是這種情況下將可能出現記憶體洩露
來看下面的程式碼
程式說明:
這裡testa* p = new testa(1);建立一塊堆記憶體
這裡return *p;按值返回,按值返回會呼叫複製建構函式給值賦予給新建個物件m
程式結束後呼叫m的解構函式,但是這裡new出來的記憶體空間已經沒有可以指向的指標
因為p已經釋放,而返回的是*p,這塊記憶體已經洩露。我們跑一下看看:
in func function --呼叫func函式
create a object --new建立的testa的堆記憶體 testa* p = new testa(1);
0x1914010 --new的地址 cout<<p<<endl;
end func --結束func函式 cout<<"end func\n";
copy funcation --按值返回撥用複製建構函式,將值賦予給新的變數m testa m = func();
0x7fffb9c438a0 --新物件m的地址cout<<&m<<endl;
1
discard a object --解構函式釋放棧物件m的空間
這裡我們發現new的堆記憶體空間沒有被析構,那麼記憶體已經洩露。
那麼我們怎麼不大量改變程式的情況下來消除這種問題呢
當然是使用指標或者引用來返回
這一在main中我把定義m指標到刪除放到了一個block中,這樣在block結束的時候就釋放了m避免了空指標的存在。
下面是引用
同樣main中的這個程式塊是為了避免空引用
輸出如下:
in func function
create a object
0x1989010
end func
0x1989010
1
discard a object
可以看到地址都相同,最後的解構函式是我呼叫delete執行的。
1、函式按值傳遞和按值返回的時候都會呼叫複製建構函式
2、一般在函式體內定義的棧變數是不能返回其地址或者引用給主調函式的,因為在函式結束的時候這些棧變數將釋放
3、可以使用new的方式建立堆記憶體的方式,然後返回引用或者指標,因為new這種方式建立的堆記憶體並不隨函式的結束而結束,
而指標變數釋放但是指標本生的值已經返回。同時也可以按值放回,但是這種情況下將可能出現記憶體洩露
來看下面的程式碼
點選(此處)摺疊或開啟
-
/*************************************************************************
-
> File Name: testcc.cpp
-
> Author: gaopeng
-
> Mail: gaopp_200217@163.com
-
> Created Time: Thu 01 Sep 2016 09:06:53 PM CST
-
************************************************************************/
-
-
#include<iostream>
-
using namespace std;
-
-
-
class testa
-
{
-
private:
-
int i;
-
public:
-
testa(const int m){
-
cout<<"create a object\n";
-
i=m;
-
}
-
const int& geti() const {
-
return i;
-
}
-
testa(const testa& m ){
-
cout<<"copy funcation\n";
-
i=m.i;
-
}
-
~testa(){
-
cout<<"discard a object\n";
-
}
-
testa operator=(const testa& c)
-
{
-
cout<<"= funcation\n";
-
i = c.i;
-
}
-
-
};
-
-
testa func()
-
{
-
cout<<"in func function\n";
-
//testa p(10);
-
testa* p = new testa(1);
-
cout<<p<<endl;
-
cout<<"end func\n";
-
return *p;
-
}
-
-
-
int main(void)
-
{
-
testa m = func(); //copy
-
cout<<&m<<endl;
-
cout<<m.geti()<<endl;
-
return 0;
- }
這裡testa* p = new testa(1);建立一塊堆記憶體
這裡return *p;按值返回,按值返回會呼叫複製建構函式給值賦予給新建個物件m
程式結束後呼叫m的解構函式,但是這裡new出來的記憶體空間已經沒有可以指向的指標
因為p已經釋放,而返回的是*p,這塊記憶體已經洩露。我們跑一下看看:
in func function --呼叫func函式
create a object --new建立的testa的堆記憶體 testa* p = new testa(1);
0x1914010 --new的地址 cout<<p<<endl;
end func --結束func函式 cout<<"end func\n";
copy funcation --按值返回撥用複製建構函式,將值賦予給新的變數m testa m = func();
0x7fffb9c438a0 --新物件m的地址cout<<&m<<endl;
1
discard a object --解構函式釋放棧物件m的空間
這裡我們發現new的堆記憶體空間沒有被析構,那麼記憶體已經洩露。
那麼我們怎麼不大量改變程式的情況下來消除這種問題呢
當然是使用指標或者引用來返回
點選(此處)摺疊或開啟
-
testa* func()
-
{
-
cout<<"in func function\n";
-
//testa p(10);
-
testa* p = new testa(1);
-
cout<<p<<endl;
-
cout<<"end func\n";
-
return p;
-
}
-
-
-
int main(void)
-
{
-
{
-
testa* m = func(); //copy
-
cout<<m<<endl;
-
cout<<m->geti()<<endl;
-
delete m;
-
}
-
return 0;
- }
下面是引用
點選(此處)摺疊或開啟
-
testa& func()
-
{
-
cout<<"in func function\n";
-
//testa p(10);
-
testa* p = new testa(1);
-
cout<<p<<endl;
-
cout<<"end func\n";
-
return *p;
-
}
-
-
-
int main(void)
-
{
-
{
-
testa& m = func(); //copy
-
cout<<&m<<endl;
-
cout<<m.geti()<<endl;
-
delete &m;
-
}
-
return 0;
- }
輸出如下:
in func function
create a object
0x1989010
end func
0x1989010
1
discard a object
可以看到地址都相同,最後的解構函式是我呼叫delete執行的。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2123621/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- IE中的記憶體洩露記憶體洩露
- C++記憶體洩露檢查的5個方法C++記憶體洩露
- 關於Javascript記憶體洩露的那些小事兒JavaScript記憶體洩露
- JavaScript中的記憶體洩露模式JavaScript記憶體洩露模式
- 記憶體洩露記憶體洩露
- java 產生一個Java的記憶體洩露Java記憶體洩露
- 關於java中的記憶體洩漏Java記憶體
- 一個 Vue 頁面的記憶體洩露分析Vue記憶體洩露
- 一個Vue頁面的記憶體洩露分析Vue記憶體洩露
- js記憶體洩露JS記憶體洩露
- JavaScript記憶體洩露JavaScript記憶體洩露
- 記憶體洩露嗎記憶體洩露
- 關於C++ delete 來釋放new分配的記憶體C++delete記憶體
- c++ 虛解構函式[避免記憶體洩漏]C++函式記憶體
- 【c++】vector.clear()的記憶體洩露問題C++記憶體洩露
- Android中Handler引起的記憶體洩露Android記憶體洩露
- 如何診斷 Java 中的記憶體洩露Java記憶體洩露
- Android 中 Handler 引起的記憶體洩露Android記憶體洩露
- js記憶體洩露的原因JS記憶體洩露
- Java記憶體洩露的原因Java記憶體洩露
- JAVA 記憶體洩露的理解Java記憶體洩露
- 從預設解構函式學習c++,new,delete,記憶體洩漏,野指標函式C++delete記憶體指標
- 記一次Go websocket 專案記憶體洩露排查 + 使用Go pprof定位記憶體洩露GoWeb記憶體洩露
- 記憶體溢位和記憶體洩露記憶體溢位記憶體洩露
- java中如何檢視記憶體洩露Java記憶體洩露
- 關於c語言記憶體分配,malloc,free,和段錯誤,記憶體洩露C語言記憶體洩露
- Lowmemorykiller記憶體洩露分析記憶體洩露
- 避免使用不當pthread_create函式造成記憶體洩露thread函式記憶體洩露
- Volley中listener導致的記憶體洩露記憶體洩露
- 檢視 Node.js 中的記憶體洩露Node.js記憶體洩露
- Golang記憶體分配內建函式之new函式Golang記憶體函式
- LeakCanary 傻瓜式的記憶體洩露檢測工具記憶體洩露
- LeakCanary傻瓜式的記憶體洩露檢測工具記憶體洩露
- 記憶體洩露引起的問題記憶體洩露
- ThreaLocal記憶體洩露的問題記憶體洩露
- Android 關於記憶體洩露,你必須瞭解的東西Android記憶體洩露
- 一種不易察覺的記憶體洩露 (轉)記憶體洩露
- 記一次"記憶體洩露"排查過程記憶體洩露