關於C 語言的記憶體管理的一些小知識

2021-10-06 02:15:05 字數 4038 閱讀 5562

在這篇部落格中,來簡單介紹一下在c++語言的一點記憶體管理的小知識,在這之前我還寫了一篇關於c語言的記憶體管理的小知識,如果感興趣的同學可以翻到前面看一下那篇部落格,給小弟增加點瀏覽量。

話不多說,進入正題:

c++記憶體管理方式:

c語言記憶體管理方式在c++中可以繼續使用,但有些地方就無能為力而且使用起來比較麻煩,因此c++又提出了自己的記憶體管理方式:通過new和delete操作符來進行動態記憶體管理。

void

test()

注意:申請和釋放單個元素的空間,使用new和delete操作符,申請和釋放連續的空間,使用new和

delete

class

test

~test()

private

:int _data;};

void

test2()

void

test2()

注意:在申請自定義型別的空間時,new會呼叫建構函式,delete會呼叫析構函式,而malloc與free不會。

new和delete是使用者進行動態記憶體申請和釋放的操作符,operator new 和operator delete是系統提供的

全域性函式,new在底層呼叫operator new全域性函式來申請空間,delete在底層通過operator delete全域性

函式來釋放空間。

/*

operator new:該函式實際通過malloc來申請空間,當malloc申請空間成功時直接返回;申請空間失敗,

嘗試執行空 間不足應對措施,如果改應對措施使用者設定了,則繼續申請,否則拋異常。

*/void

*__crtdecl operator

new(size_t size)

_throw1

(_std bad_alloc)

return

(p);}/*

operator delete: 該函式最終是通過free來釋放空間的

*/void

operator

delete

(void

*puserdata)

通過上述兩個全域性函式的實現知道,operator

new 實際也是通過malloc來申請空間,如果malloc申請空間

成功就直接返回,否則執行使用者提供的空間不足應對措施,如果使用者提供該措施就繼續申請,否則就拋異常。operator

delete 最終是通過free來釋放空間的

下面**演示了,針對鍊錶的節點listnode通過過載類專屬 operator new/ operator delete,實現鍊錶節點使用記憶體池申請和釋放記憶體,提高效率。

struct listnode

void

operator

delete

(void

* p)};

class

list

~list()

delete _head;

_head =

nullptr;}

private

: listnode* _head;};

intmain()

new和delete的實現原理內建型別

如果申請的是內建型別的空間,new和malloc,delete和free基本類似,不同的地方是:new/delete申請和釋放的是單個元素的空間,new和delete申請的是連續空間,而且new在申請空間失敗時會拋異常,malloc會返回null。

自定義型別

new的原理

呼叫operator new函式申請空間

在申請的空間上執行建構函式,完成物件的構造

delete的原理

在空間上執行析構函式,完成物件中資源的清理工作

呼叫operator delete函式釋放物件的空間

new t[n]的原理

呼叫operator new函式,在operator new中實際呼叫operator new函式完成n個物件空間的申

請在申請的空間上執行n次建構函式

delete的原理

在釋放的物件空間上執行n次析構函式,完成n個物件中資源的清理

呼叫operator delete釋放空間,實際在operator delete中呼叫operator delete來釋放空間

定位new表示式(placement-new)

定位new表示式是在已分配的原始記憶體空間中呼叫建構函式初始化乙個物件。

使用格式

new (place_address) type或者new (place_address) type(initializer-list)

place_address必須是乙個指標,initializer-list是型別的初始化列表

使用場景:

定位new表示式在實際中一般是配合記憶體池使用。因為記憶體池分配出的記憶體沒有初始化,所以如果是自定義

型別的物件,需要使用new的定義表示式進行顯示調建構函式進行初始化

class

test

~test()

private

:int _data;};

void

test()

malloc/free和new/delete的共同點是:都是從堆上申請空間,並且需要使用者手動釋放。不同的地方是:

malloc和free是函式,new和delete是操作符

malloc申請的空間不會初始化,new可以初始化

malloc申請空間時,需要手動計算空間大小並傳遞,new只需在其後跟上空間的型別即可

malloc的返回值為void*, 在使用時必須強轉,new不需要,因為new後跟的是空間的型別

malloc申請空間失敗時,返回的是null,因此使用時必須判空,new不需要,但是new需要捕獲異常

申請自定義型別物件時,malloc/free只會開闢空間,不會呼叫建構函式與析構函式,而new在申請空間後會呼叫建構函式完成物件的初始化,delete在釋放空間前會呼叫析構函式完成空間中資源的清理。

什麼是記憶體洩漏:記憶體洩漏指因為疏忽或錯誤造成程式未能釋放已經不再使用的記憶體的情況。記憶體洩漏並不是指內存在物理上的消失,而是應用程式分配某段記憶體後,因為設計錯誤,失去了對該段記憶體的控制,因而造成了記憶體的浪費。

記憶體洩漏的危害:長期執行的程式出現記憶體洩漏,影響很大,如作業系統、後台服務等等,出現記憶體洩漏會導致響應越來越慢,最終卡死

void

memoryleaks()

記憶體洩漏分類c/c++程式中一般我們關心兩種方面的記憶體洩漏:

堆記憶體洩漏(heap leak)

堆記憶體指的是程式執行中依據須要分配通過malloc / calloc / realloc / new等從堆中分配的一塊記憶體,用完後必須通過呼叫相應的 free或者delete 刪掉。假設程式的設計錯誤導致這部分記憶體沒有被釋放,那麼以後這部分空間將無法再被使用,就會產生heap leak。

系統資源洩漏

指程式使用系統分配的資源,比方套接字、檔案描述符、管道等沒有使用對應的函式釋放掉,導致系統資源的浪費,嚴重可導致系統效能減少,系統執行不穩定。

如何避免記憶體洩漏

工程前期良好的設計規範,養成良好的編碼規範,申請的記憶體空間記著匹配的去釋放。ps:這個理想狀

態。但是如果碰上異常時,就算注意釋放了,還是可能會出問題。需要下一條智慧型指標來管理才有保

證。採用raii思想或者智慧型指標來管理資源。

有些公司內部規範使用內部實現的私有記憶體管理庫。這套庫自帶記憶體洩漏檢測的功能選項。

出問題了使用記憶體洩漏工具檢測。

總結一下:

記憶體洩漏非常常見,解決方案分為兩種:1、事前預防型。如智慧型指標等。2、事後查錯型。如洩漏檢測工具。

關於 vertical align 的一些小知識

在日常開發過程中,我們經常會遇到如下的場景,一行中既有也有文字,而且還要和文字對齊。效果如下 通常 如下 some text.得到的效果卻是這樣的 修改下文字為行內塊盒子,並設定行高與盒子高度 盒子高度與高度相同 一致,效果如下 我們發現文字區域始終與錯開了一些。怎麼解決呢?設定文字的 margin...

關於C 類記憶體的一些小試驗

看了一些關於c 類記憶體的文章,有了一些粗淺的了解,來做幾個小試驗檢驗我自己的認知。試驗用計算機是64位的。理論上類記憶體的大小應該是非靜態資料成員的大小加上虛指標的大小再考慮記憶體對齊。先來乙個簡單的。class base base private int a char b 這個類有多大呢,64位...

關於C 的一些小知識

不行,可以這樣理解 static修飾的方法可以直接用類名呼叫 非static修飾的方法必須用類new出物件才能呼叫 當我們用類名直接呼叫時,可能這個類的物件並沒有new。如果這時候static方法裡呼叫非static的方法就會出現空指標異常,當然這種錯誤編譯時就不會通過。錯誤 演示 1 class ...