c++ 建構函式丟擲異常會引起記憶體洩漏嗎?
我們用實際**說明問題:先看一下如下**:
#include
using namespace std;
class inner
public:
inner()
cout<
~inner()
cout<
class outer
private:
int m_value;
inner inner1;
public:
outer(int value):m_value(value)
cout<
throw 3;
~outer()
cout<
void* operator new(size_t size)
cout<
unsigned char* tmp = ::new unsigned char[size];
return tmp;
void operator delete(void* ptr)
cout<
::delete (unsigned char*)ptr;
main()
tryouter* d = new outer(1);
catch(...)
cout<
這段**編譯後執行結果:
void* operator new(size_t size)
inner()
outer(int value)
~inner()
void* operator delete(void* ptr)
exception got it
從**執行結果來看,我們可以得出如下結論:
1. new乙個物件有兩個過程:
a.向系統申請記憶體空間
b.在申請的記憶體空間上執行建構函式,初始化物件。
2.內部物件構造先於物件本身。
3.物件在建構函式丟擲異常後,系統會負責清理構造物件時申請的記憶體,但不會呼叫物件析構函式。
也就是說構造物件的記憶體會被釋放掉,已經完成例項化的成員物件也會成功析構。
通過valgrind工具可以看到不存在記憶體洩漏。
下面我們把**修改一下。修改只有兩處,注意紅色標記。
#include
using namespace std;
class inner
private:
int m_value;
public:
inner()
cout<
inner(int value):m_value(value)
cout<
~inner()
cout<
class outer
private:
int m_value;
inner inner1;
public:
outer()
cout<
//throw 3;
outer(int value):m_value(value)
cout<
~outer()
cout<
void* operator new(size_t size)
cout<
unsigned char* tmp = ::new unsigned char[size];
throw 1;
return tmp;
void operator delete(void* ptr)
cout<
::delete (unsigned char*)ptr;
main()
tryouter* d = new outer(1);
catch(...)
cout<
我們改在過載的new操作符方法中丟擲異常。
程式輸出結果:
void* operator new(size_t size)
got it
是的,這個結果想必大家已經預料到了,析構和釋放記憶體的操作都沒有執行。
valgrind 的執行結果:
發生了記憶體洩漏。
過載new操作符,使用者可以在自己的記憶體池中分配記憶體去構造物件,但是如果成功申請記憶體但後續執行丟擲異常後,就會造成記憶體洩漏。
最後修改一下**,還是在建構函式中丟擲異常,注意紅色標記
#include
using namespace std;
class inner
private:
int m_value;
public:
inner()
m_value=1;
cout<
inner(int value):m_value(value)
cout<
~inner()
cout<
private:
int m_value;
inner inner1;
inner* inner2;
public:
outer()
cout<
outer(int value):m_value(value)
cout<
inner2 = new inner(2);
throw 1;
~outer()
cout<
void* operator new(size_t size)
cout<
unsigned char* tmp = ::new unsigned char[size];
return tmp;
void operator delete(void* ptr)
cout<
::delete (unsigned char*)ptr;
main()
tryouter* d = new outer(1);
catch(...)
cout<
**執行結果:
void* operator new(size_t size)
inner()
outer(int value)
inner(int value)
~inner1()
void* operator delete(void* ptr)
got it
可以看到內部成員物件inner1成功析構,但是指標inner2沒有析構(因為inner2是乙個指標,清棧的時候只會呼叫棧裡的區域性物件的析構函式,但是不會delete呼叫棧裡指標),想必大家也可以預見到這樣的情況。
valgrind的輸出:4個位元組記憶體洩漏,肯定是inner2沒有成功釋放。
可以得到如下結論:
乙個物件在建構函式中丟擲異常,物件本身的記憶體會被成功釋放,但是其析構函式不會被呼叫。其內部區域性成員物件清棧時是會被釋放掉的,故其析構函式被呼叫,但是使用者在建構函式中動態生成的物件沒有被delete掉(new出來的是乙個指標,清棧時是不會delete掉棧裡的指標)。
如果乙個物件在建構函式中開啟很多系統資源,但是建構函式中後續**丟擲了異常,則這些資源將不會被釋放,建議在建構函式中加入try catch語句,對先前申請的資源進行釋放後(也就是做析構函式該做的事情)再次丟擲異常,確保記憶體和其他資源被成功**。
C 建構函式中丟擲的異常
分類 c c 程式設計 2011 04 19 10 03 4940人閱讀收藏 舉報c exception string class測試c 建構函式中丟擲的異常 1 標準c 中定義建構函式是乙個物件構建自己,分配所需資源的地 方,一旦建構函式執行完畢,則表明這個物件已經誕生了,有自己的行為和內部的執行...
C 建構函式中丟擲的異常
建構函式中丟擲的異常 1 標準c 中定義建構函式是乙個物件構建自己,分配所需資源的地 方,一旦建構函式執行完畢,則表明這個物件已經誕生了,有自己的行為和內部的執行狀態,之後還有物件的消亡過程 析構函式的執行 可誰能保證物件的構造 過程一定能成功呢?說不定系統當前的某個資源不夠,導致物件不能完全構建好...
C 建構函式 析構函式與丟擲異常
問題 建構函式可以丟擲異常麼?析構函式可以嗎?分析 從語法上來說,建構函式和析構函式都可以丟擲異常。但從邏輯上和風險控制上,建構函式可以,析構函式不推薦丟擲異常。1 建構函式可以丟擲異常 無論何時,從建構函式中丟擲異常都是可以的。動態建立物件要進行兩個操作 分配記憶體和呼叫建構函式。若在分配記憶體時...