1. 程式人生 > >Item 50:為什麼需要自定義new和delete?

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為什麼需要定義newdelete

Item 50: Understand when it makes sense to replace new and delete. 我們在Item 49中介紹瞭如何自定義new的錯誤處理函式,以及如何為你的類過載operator new。 現在我們回到更基

com4j學習(2)Visio定義模具形狀,並新增連線點

前言: 既然我們想繪製跟自己業務相關的圖形,並讀取Visio圖形中的結構資訊,那麼我們自然會想到要自定義圖形,本文詳細講解如何自定義圖形。 正文: 首先我們要明白什麼是模具,什麼是形狀,以及兩者之間的關係?模具就相當於一個容器,裡面有很多個形狀,我們可

effective c++ 條款16成對使用newdelete時要采用相同形式

最好 class 你在 pan TE fec IV line PE 記住: 如果你在new表達式中使用[ ],必須在相應的delete表達式中也是用[ ]。如果你在new時不使用[ ],一定不要在delete時使用[ ]。 string* stringPtr1 = n

effective c++條款16成對使用newdelete時要採取相同形式

下面的程式碼會產生什麼樣的後果? #include <iostream> using namespace std; int main(void) { std::string *StringArray = new std::string[30]; delete StringAr

MySQL定義函式儲存過程的區別

  自定義函式和儲存過程的區別: 1)一般來說,儲存過程實現的功能要複雜一點,而函式的實現的功能針對性比較強。儲存過程,功能強大,可以執行包括修改表等一系列資料庫操作;使用者定義函式不能用於執行一組修改全域性資料庫狀態的操作。 2)對於儲存過程來說可以返回引數,如記錄集,而函式只能返回值或者表物件。函式只能

androidRadioButton定義定義的實現

    我簡單解釋下:當root為null的時候,我們只是把一個xml檔案例項化成View物件,反回的就是xml對應的View.而當root不為null的時候,也就是存在parent.那麼我們將把這個xml例項化程View物件後,將這個View檢視add進其parent中.所以在這裡我們用的是LayoutIn

Item 51newdelete時請遵循慣例

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_tagfilter

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如何設置頭註釋,定義authordate

技術分享 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 定義AnalyzerTokenFilter

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