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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一個 Vue 頁面的記憶體洩露分析Vue記憶體洩露
- 一個Vue頁面的記憶體洩露分析Vue記憶體洩露
- 從預設解構函式學習c++,new,delete,記憶體洩漏,野指標函式C++delete記憶體指標
- SHBrowseForFolder 記憶體洩露記憶體洩露
- 避免使用不當pthread_create函式造成記憶體洩露thread函式記憶體洩露
- Golang記憶體分配內建函式之new函式Golang記憶體函式
- 記憶體溢位和記憶體洩露記憶體溢位記憶體洩露
- Lowmemorykiller記憶體洩露分析記憶體洩露
- java中如何檢視記憶體洩露Java記憶體洩露
- ArkTS 的記憶體快照與記憶體洩露除錯記憶體洩露除錯
- 記一次"記憶體洩露"排查過程記憶體洩露
- 使用 mtrace 分析 “記憶體洩露”記憶體洩露
- 實戰Go記憶體洩露Go記憶體洩露
- Android 記憶體洩露詳解Android記憶體洩露
- android Handler導致的記憶體洩露Android記憶體洩露
- Linux記憶體洩露案例分析和記憶體管理分享Linux記憶體洩露
- 關於PHP記憶體洩漏的問題PHP記憶體
- nodejs爬蟲記憶體洩露排查NodeJS爬蟲記憶體洩露
- Pprof定位Go程式記憶體洩露Go記憶體洩露
- 一次Kafka記憶體洩露排查經過Kafka記憶體洩露
- 記一次 .NET 某工控軟體 記憶體洩露分析記憶體洩露
- 簡單的記憶體“洩露”和“溢位”記憶體
- JAVA記憶體洩露的原因及解決Java記憶體洩露
- Python實現記憶體洩露排查的示例Python記憶體洩露
- 關於C++當中的“模板函式”C++函式
- win10驅動記憶體洩露如何解決_win10記憶體洩露處理方法Win10記憶體洩露
- 記一次尷尬的Java應用記憶體洩露排查Java記憶體洩露
- 分散式 | 令人頭疼的堆外記憶體洩露怎麼排查?分散式記憶體洩露
- netty 堆外記憶體洩露排查盛宴Netty記憶體洩露
- 乾貨分享:淺談記憶體洩露記憶體洩露
- 解決git記憶體洩露問題Git記憶體洩露
- Spring Boot heapdump洩露記憶體分析方法Spring Boot記憶體
- 線上記憶體洩露定位--memleak工具記憶體洩露
- C++動態記憶體管理——new/deleteC++記憶體delete
- C++記憶體管理:new / delete 和 cookieC++記憶體deleteCookie
- JVM記憶體洩露(OOM)!帶你一一揭秘【第一彈】JVM記憶體洩露OOM
- C程式記憶體洩露檢測工具——ValgrindC程式記憶體洩露
- Android效能最佳化之記憶體洩露Android記憶體洩露
- 小題大做 | Handler記憶體洩露全面分析記憶體洩露