Item 50:為什麼需要自定義new和delete?
Item 50: Understand when it makes sense to replace new and delete.
我們在Item 49中介紹瞭如何自定義new的錯誤處理函式,以及如何為你的類過載operator new。 現在我們回到更基礎的問題,為什麼我們需要自定義operator new或operator delete?
- 檢測使用錯誤。new得到的記憶體如果沒有delete會導致記憶體洩露,而多次delete又會引發未定義行為。如果自定義operator new來儲存動態記憶體的地址列表,在delete中判斷記憶體是否完整,便可以識別使用錯誤,避免程式崩潰的同時還可以記錄這些錯誤使用的日誌。
- 提高效率。全域性的new和delete被設計為通用目的(general purpose)的使用方式,通過提供自定義的new,我們可以手動維護更適合應用場景的儲存策略。
- 收集使用資訊。在繼續自定義new之前,你可能需要先自定義一個new來收集地址分配資訊,比如動態記憶體塊大小是怎樣分佈的?分配和回收是先進先出FIFO還是後進先出LIFO?
- 實現非常規的行為。比如考慮到安全,operator new把新申請的記憶體全部初始化為0.
- 其他原因,比如抵消平臺相關的位元組對齊,將相關的物件放在一起等等。
自定義一個operator new很容易的,比如實現一個支援越界檢查的new:
static const int signature = 0xDEADBEEF; // 邊界符
typedef unsigned char Byte;
void* operator new(std::size_t size) throw(std::bad_alloc) {
// 多申請一些記憶體來存放佔位符
size_t realSize = size + 2 * sizeof(int);
// 申請記憶體
void *pMem = malloc(realSize);
if (!pMem) throw bad_alloc();
// 寫入邊界符
*(reinterpret_cast <int*>(static_cast<Byte*>(pMem)+realSize-sizeof(int)))
= *(static_cast<int*>(pMem)) = signature;
// 返回真正的記憶體區域
return static_cast<Byte*>(pMem) + sizeof(int);
}
其實上述程式碼是有一些瑕疵的:
- Item 49提到operator new應當不斷地呼叫new handler,上述程式碼中沒有遵循這個慣例;
- 有些體系結構下,不同的型別被要求放在對應的記憶體位置。比如double的起始地址應當是8的整數倍,int的起始地址應當是4的整數倍。上述程式碼可能會引起執行時硬體錯誤。
- 起始地址對齊。C++要求動態記憶體的起始地址對所有型別都是位元組對齊的,new和malloc都遵循這一點,然而我們返回的地址偏移了一個int。
到此為止你已經看到了,實現一個operator new很容易,但實現一個好的operator new卻很難。其實我們還有別的選擇:比如去讀編譯器文件、記憶體管理的商業工具、開源記憶體管理工具等。
相關推薦
Item 50:為什麼需要自定義new和delete?
Item 50: Understand when it makes sense to replace new and delete. 我們在Item 49中介紹瞭如何自定義new的錯誤處理函式,以及如何為你的類過載operator new。 現在我們回到更基
com4j學習(2):Visio自定義模具和形狀,並新增連線點
前言: 既然我們想繪製跟自己業務相關的圖形,並讀取Visio圖形中的結構資訊,那麼我們自然會想到要自定義圖形,本文詳細講解如何自定義圖形。 正文: 首先我們要明白什麼是模具,什麼是形狀,以及兩者之間的關係?模具就相當於一個容器,裡面有很多個形狀,我們可
effective c++ 條款16:成對使用new和delete時要采用相同形式
最好 class 你在 pan TE fec IV line PE 記住: 如果你在new表達式中使用[ ],必須在相應的delete表達式中也是用[ ]。如果你在new時不使用[ ],一定不要在delete時使用[ ]。 string* stringPtr1 = n
effective c++條款16:成對使用new和delete時要採取相同形式
下面的程式碼會產生什麼樣的後果? #include <iostream> using namespace std; int main(void) { std::string *StringArray = new std::string[30]; delete StringAr
MySQL自定義函式和儲存過程的區別:
自定義函式和儲存過程的區別: 1)一般來說,儲存過程實現的功能要複雜一點,而函式的實現的功能針對性比較強。儲存過程,功能強大,可以執行包括修改表等一系列資料庫操作;使用者定義函式不能用於執行一組修改全域性資料庫狀態的操作。 2)對於儲存過程來說可以返回引數,如記錄集,而函式只能返回值或者表物件。函式只能
android:RadioButton自定義和非自定義的實現
我簡單解釋下:當root為null的時候,我們只是把一個xml檔案例項化成View物件,反回的就是xml對應的View.而當root不為null的時候,也就是存在parent.那麼我們將把這個xml例項化程View物件後,將這個View檢視add進其parent中.所以在這裡我們用的是LayoutIn
Item 51:寫new和delete時請遵循慣例
Item 51: Adhere to convention when writing new and delete. Item 50介紹瞭如何自定義new和delete但沒有解釋你必須遵循的慣例, 這些慣例中有些並不直觀,所以你需要記住它們! opera
######Spring第5天ssh整合(註解版)難理解知識點:【自定義 方法加註解的方式】給dao注入sessionFactory屬性+【搞清@Autowared和@Resource含義】
===【方法加註解的方式】給dao注入sessionFactory屬性(繼承父類的屬性),第一次見!===具體怎麼用的,看原始碼。(後面有寫) 以前都是屬性+註解注入屬性。 [email protected]和@Resource到底是幹嘛的? 剛學IOC時可能能
分針網——每日分享:CSS 自定義屬性:API 篇
css JQuery是一個非常優秀的js庫。 選擇元素 $( )裏可以填css選擇器 $(’.demo’).
實戰案例:構建docker容器集群 (解決方案一:使用自定義網橋連接跨主機容器)
docker一、實驗環境虛擬機a兩塊網卡 eth0 eth1 (IP地址static或者dhcp)虛擬機b兩塊網卡 eth0 eth1 (IP地址static或者dhcp)二、在兩臺虛擬機上配置網橋虛擬機a操作:apt-get install bridge-utilsvim /etc/ne
freemarker實現自定義指令和自定義函數
數據 dir variables macro 內置 引擎 eem fig turn 自定義指令: 1.指令在前臺實現 <#macro name param1,param2,param3...paramN> </#macro> 2.指令在後臺實
在 Windows Server Container 中運行 Azure Storage Emulator(二):使用自定義的 SQL Server Instance
manage span contain target ros 結果 images 兩種方法 ini 上一章,我們解決了 Azure Storage Emulator 自定義監聽地址的問題,這遠遠不夠,因為在我們 DEV/QA 環境有各自的 SQL Server Inst
18)django-模板的過濾器和tag,自定義simple_tag和filter
hello 直接 結果 from simple 使用 span 裝飾 san 模板過濾器是在變量被顯示前修改它的值的一個簡單方法。 過濾器使用管道字符 . 模板標簽(template tag) 。標簽(tag)定義比較明確,即: 僅通知模板系統完成某些工作的標簽。 一:d
Kivy 中文教程 實例入門 簡易畫板 (Simple Paint App):1. 自定義窗口部件 (widget)
mage 動作 顯示 lac one 參數 sublime elf 入門 1. 框架代碼 用 PyCharm 新建一個名為 SimplePaintApp 的項目,然後新建一個名為 simple_paint_app.py 的 Python 源文件, 在代碼編輯器中,輸入以下框
IntelliJ IDEA如何設置頭註釋,自定義author和date
技術分享 spa 分享圖片 es2017 log tel auth bsp image 下面這張圖,保證你一看就會: 下面這個模板,你拿去改一改就行了。 1 /** 2 * @Author: Gosin 3 * @Date: ${DATE} ${TIME} 4 */
使用自定義註解和反射 ,自動生成查詢語句
runt entity forname == rop ava stat pri string 1.自定義表名註解 package com.lf.annotation; import java.lang.annotation.ElementType; import jav
SSH開發 | 配合自定義註解 和 Stratus攔截器,實現 方法級粒度 用戶鑒權
struts OS action gin 所有 具體實現 getmethod red nal 1.提要 本文是 小小商城-SSH版的 細節詳解系列 之一,項目 github:https://github.com/xenv/S-mall-ssh 本文代碼大部分在 gith
Vue自定義指令和路由
class 在哪裏 lan tps 定時 簡單的 cdn 可用 string 一、自定義指令 除了默認設置的核心指令( v-model 和 v-show ), Vue 也允許註冊自定義指令。 下面我們註冊一個全局指令 v-focus,該指令的功能是在頁面加載時,元素
Lucene 7.2.1 自定義Analyzer和TokenFilter
oge close protect .get one AC put stand hash 1.自定義Analyzer: import com.dys.lucene.filter.SameWordTokenFilter; import org.apache.lucene.a
asp.net core中遇到需要自定義數據包解密方法的時候
聲明 AD AR 但是 sof AC asp 參數聲明 request 最近將公司的項目用.netcore重寫, 服務的http外部接口部分收發消息是DES加解密的, 那麽在asp.net core mvc的action處理之前需要加入解密這個步驟. 我第一想到的是用f