棧又叫堆棧,非靜態局部變量/函數參數/返回值等,棧是向下增長的
內存映射段是高效I/O映射方式,用於裝載一個共享的動態內存庫 。用戶可以使用系統接口創建共享內存,做進程間的通信
堆用於程序運行時動態內存分配,堆是可以上增長
數據段存儲全局數據和靜態數據
代碼段可執行的代碼/只讀常量
C語言中動態內存管理方式
- malloc/calloc/realloc和free
void test()
{
int* p1= (int*)malloc(sizeof(int));
free(p1);
int* p2= (int*)calloc(4,sizeof(int));
int* p3= (int*)realloc(p2,sizeof(int)*10);
free(p2);
free(p3);
}
malloc/calloc/realloc的區別
相同點:
1.都是從堆上申請空間;
2.都需要對返回值判空;
3.都需要用戶free釋放;
4.返回值類型相同(都是void*);
5.都需要類型轉化;
6.底層實現是一樣的,都需要開闢多餘的空間,用來維護申請的空間。
不同點:
1.函數名字不同,參數類型不同;
2.calloc函數會對申請空間初始化,並且初始化爲0;
3.malloc函數申請空間必須使用memset進行初始化;
4.realloc函數是對已經存在的空間進行調整,當第一個參數傳入NULL的時候和malloc函數一樣
C++內存管理方式
C語言的內存管理方式在C++中仍然可以繼續使用,但有的地方用起來比較麻煩,於是C++提出了自己的內存管理方式:通過new和delete操作符進行動態內存管理
class test
{
public:
test()
:_data(0)
{
cout << "test():" << this << endl;
}
~test()
{
cout << "~test():" << this << endl;
}
private:
int _data;
};
void test2()
{
//申請單個test類型的空間
test* p1 = (test*)malloc(sizeof(test));
free(p1);
//申請10個test類型的空間
test* p2 = (test*)malloc(sizeof(test)* 10);
free(p2);
}
void test2()
{
//申請單個test類型的對象
test* p1 = new test;
delete p1;
//申請10個test類型的對象
test* p2 = new test[10];
delete[] p2;
}
在申請自定義類型的空間是,new會調用構造函數,delete會調用析構函數,而malloc和free則不會
operator new 與operator delete函數
new和delete是用戶進行動態內存申請和釋放的操作符,operator new 和operator delete是系統提供的全局函數,new在底層調用operator new全局函數來申請空間,delete在底層通過operator delete全局函數來釋放空間。
operator new 實際通過malloc來申請空間,當malloc申請空間成功時之間返回,申請空間失敗,嘗試執行空間不足應對措施,如果應對措施用戶設置了,則繼續申請,否則拋異常
operator delete 是通過free來釋放空間的
new和delete的實現原理
如果申請的是內置類型的空間,new和malloc,delete和free基本類似,不同的地方是。new/delete申請和釋放的是單個元素的空間,new[]和delete[]申請的事連續 的空間,而且new在申請空間失敗時會拋異常,malloc會返回NULL
new的原理
1. 調用operator new函數申請空間 2. 在申請的空間上執行構造函數,完成對象的構造
delete的原理
1. 在空間上執行析構函數,完成對象中資源的清理工作 2. 調用operator delete函數釋放對象的空間
new T[N]的原理
1. 調用operator new[]函數,在operator new[]中實際調用operator new函數完成N個對象空間的請 2. 在申請的空間上執行N次構造函數
delete[]的原理
1. 在釋放的對象空間上執行N次析構函數,完成N個對象中資源的清理 2. 調用operator delete[]釋放空間,實際在operator delete[]中調用operator delete來釋放空間
malloc/free和new/delete的區別
malloc/free和new/delete的共同點是:
都是從堆上申請空間,並且需要用戶手動釋放。
不同的地方是:
1. malloc和free是函數,new和delete是操作符
2. malloc申請的空間不會初始化,new可以初始化
3. malloc申請空間時,需要手動計算空間大小並傳遞,new只需在其後跟上空間的類型即可
4. malloc的返回值爲void*, 在使用時必須強轉,new不需要,因爲new後跟的是空間的類型
5. malloc申請空間失敗時,返回的是NULL,因此使用時必須判空,new不需要,但是new需要捕獲異常
6. 申請自定義類型對象時,malloc/free只會開闢空間,不會調用構造函數與析構函數,而new在申請空間 後會調用構造函數完成對象的初始化,delete在釋放空間前會調用析構函數完成空間中資源的清理
7. new/delete比malloc和free的效率稍微低點,因爲new/delete的底層封裝了malloc/free
內存泄漏
內存泄漏指因爲疏忽或錯誤造成程序未能釋放已經不再使用的內存的情況。內存泄漏並不是指內存在物理上的消失,而是應用程序分配某段內存後,因爲設計錯誤,失去了對該段內存的控制,因而造成了內存的浪費。
void MemoryLeaks()
{
// 1.內存申請了忘記釋放
int* p1 = (int*)malloc(sizeof(int));
int* p2 = new int;
// 2.異常安全問題
int* p3 = new int[10];
Func(); // 這裏Func函數拋異常導致 delete[] p3未執行,p3沒被釋放.
delete[] p3;
}
C/C++程序中一般我們關心兩種方面的內存泄漏:
堆內存泄漏(Heap leak)
堆內存指的是程序執行中依據須要分配通過malloc / calloc / realloc / new等從堆中分配的一塊內存, 用完後必須通過調用相應的 free或者delete 刪掉。假設程序的設計錯誤導致這部分內存沒有被釋放,那 麼以後這部分空間將無法再被使用,就會產生Heap Leak。
系統資源泄漏
指程序使用系統分配的資源,比方套接字、文件描述符、管道等沒有使用對應的函數釋放掉,導致系統 資源的浪費,嚴重可導致系統效能減少,系統執行不穩定。