欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

DeepRouteLab|C++內(nèi)存管理介紹-創(chuàng)新互聯(lián)

成都創(chuàng)新互聯(lián)是專業(yè)的青山網(wǎng)站建設(shè)公司,青山接單;提供網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行青山網(wǎng)站開發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!

文章概述

內(nèi)存管理對(duì)于每種開發(fā)語(yǔ)言來(lái)說(shuō)都是一個(gè)十分重要的話題;即使像Java這種擁有“復(fù)雜”垃圾收集器的語(yǔ)言,也會(huì)面臨GC帶來(lái)的各種困擾。

C++程序設(shè)計(jì)中的很多bug也是因?yàn)閮?nèi)存管理不善導(dǎo)致的,而且難以發(fā)現(xiàn)和排除;如何有條理地管理內(nèi)存,對(duì)于C++開發(fā)尤為重要。

“他山之石可以攻玉”,在研究如何做好C++內(nèi)存管理之前,我們也可以看下其他語(yǔ)言是怎么做內(nèi)存管理的,有什么模式或者模型能為我們所借鑒,能夠更好地幫助我們理解和做好C++的內(nèi)存管理。

01

不同語(yǔ)言的內(nèi)存管理機(jī)制介紹

C/C++、Java、Objective-C/Swift 和Golang 是幾種使用廣泛的語(yǔ)言,內(nèi)存管理機(jī)制也相對(duì)典型。

1.1 C/C++

C??也常被稱作“可移植的匯編”,誕生之初主要是解決匯編語(yǔ)言的移植問題,在嵌入式和操作系統(tǒng)等相對(duì)底層的開發(fā)領(lǐng)域應(yīng)用廣泛;對(duì)于復(fù)雜的業(yè)務(wù)問題,因?yàn)樗鼪]有面向?qū)ο蟮哪芰Γú缓贸橄髽I(yè)務(wù)邏輯),顯得難以應(yīng)付。

C++?是一種很弱的面向?qū)ο蟮恼Z(yǔ)言(模版和Interface幾乎是一種相互違背的思想)。為了兼容幾乎所有的C特性,背上了比較重的歷史包袱。在C++11之后,這種現(xiàn)象有了比較大程度的改善,各種新的語(yǔ)言特性可以讓C++開發(fā)者開發(fā)出更優(yōu)雅、健壯的代碼。

C語(yǔ)言的內(nèi)存管理是典型的手動(dòng)管理機(jī)制,通過malloc申請(qǐng),free釋放。

C++語(yǔ)言除了手動(dòng)管理之外,還擁有弱的“垃圾回收機(jī)制”(智能指針的支持)。

C/C++中常見的內(nèi)存管理問題有:

a. 數(shù)組訪問越界

(Java語(yǔ)言可拋出ArrayIndexOutOfBoundsException)

b. 內(nèi)存訪問超越生命周期

??棧彈出之后,依舊進(jìn)行訪問

(函數(shù)返回內(nèi)部棧地址)

??堆內(nèi)存釋放,依舊進(jìn)行訪問

c.?內(nèi)存泄露?(沒有釋放不再使用的內(nèi)存)

d.?懸空指針導(dǎo)致的問題

??指針指向內(nèi)存釋放之后,指針沒有復(fù)位(設(shè)置為nullptr)

??使用沒有復(fù)位(不為null)的無(wú)效內(nèi)存(已釋放或者未申請(qǐng)的內(nèi)存)

e. C++獨(dú)有的問題

??非預(yù)期內(nèi)的拷貝構(gòu)造函數(shù)調(diào)用帶來(lái)的過度復(fù)制(性能問題)

??不合理的復(fù)制、拷貝構(gòu)造函數(shù)的實(shí)現(xiàn),導(dǎo)致的意外數(shù)據(jù)共享(沒有設(shè)置為nocopyable)

1.2 Java

Java 是一種面向?qū)ο蟮默F(xiàn)代語(yǔ)言,有著豐富的語(yǔ)言特性和開發(fā)生態(tài)。Java語(yǔ)言是為了實(shí)現(xiàn)下一代智能家電的通用系統(tǒng)而設(shè)計(jì)的。在借鑒C++語(yǔ)言的基礎(chǔ)上,又摒棄了C++

的一些復(fù)雜特性(可能降低軟件開發(fā)質(zhì)量)。

比如:

a.?不允許多繼承

b. 更純粹的interface

c.?所有皆對(duì)象(基礎(chǔ)類型除外)

d. non-static方法默認(rèn)支持多態(tài)

e. 等等

不想“有心栽花花不開,無(wú)心插柳柳成蔭”。

Java 在家電市場(chǎng)毫無(wú)起色,卻因?yàn)閮?yōu)異的網(wǎng)絡(luò)編程支持能力、平臺(tái)無(wú)關(guān)性、垃圾回收等能力,加上恰逢互聯(lián)網(wǎng)時(shí)代的到來(lái),而后在企業(yè)級(jí)市場(chǎng)上大放異彩。

Java 因?yàn)橛刑摂M機(jī)的支持(先編譯成字節(jié)碼,由虛擬機(jī)解釋成不同平臺(tái)的“語(yǔ)言”),可以做到“一次編譯,到處運(yùn)行”。

Java 目前在后臺(tái)開發(fā)、大數(shù)據(jù)以及App開發(fā)領(lǐng)域(Kotlin也是類Java語(yǔ)言)有著非常廣泛的應(yīng)用。

Java 的內(nèi)存管理依托于JVM的垃圾回收器(Garbage Collections)

一般而言,垃圾回收的步驟包括兩步:

a. 找到可被回收的對(duì)象;

b. 進(jìn)行內(nèi)存回收和整理

JVM(HotSpot)的GC也是如此。

(一)可收回對(duì)象判斷

JVM GC基于可達(dá)分析,來(lái)查找可回收對(duì)象;可以避免引用計(jì)數(shù)方案的循環(huán)引用問題。

? (圖1 基于根的可達(dá)對(duì)象分析)

(二)可回收策略和算法

幾乎所有的垃圾回收器,都存在STW問題,高效回收以及降低對(duì)業(yè)務(wù)代碼執(zhí)行的影響是一件很難的事情。為了盡可能地優(yōu)化性能,GC采用?分代收集?和?標(biāo)記-清除/標(biāo)記-清除-整理/標(biāo)記-復(fù)制?進(jìn)行內(nèi)存回收。

??分代收集 (新生代和老年代)

不難理解,新申請(qǐng)的內(nèi)存比較大的概率可以在不久后刪除;如果一個(gè)內(nèi)存存在比較久了,那么接下來(lái)被回收的概率就會(huì)比較低;新生代的回收會(huì)比較輕量和高效,老年代的GC相對(duì)會(huì)比較重。

-?G1之前基本都是下圖這種典型的分代內(nèi)存模型。

(圖2 典型的內(nèi)存分代模型)

- G1仍然保留了新生代和老年代的概念,但是新生代和老年代的內(nèi)存區(qū)域不再固定,都是一系列的動(dòng)態(tài)集合。

(圖3?G1的內(nèi)存分代模型)

??標(biāo)記-清除/標(biāo)記-清除-整理/標(biāo)記-復(fù)制

-?標(biāo)記-清除?方法相對(duì)簡(jiǎn)單、高效,但是會(huì)存在內(nèi)存碎片;

-?標(biāo)記-清除-整理?可以解決內(nèi)存碎片的問題,但是會(huì)增加GC的持續(xù)時(shí)間(好處大于壞處);

-?標(biāo)記-復(fù)制?方法類似于ping-pang機(jī)制,需要有兩片內(nèi)存區(qū)域;在內(nèi)存清理階段,會(huì)將存活對(duì)象統(tǒng)一放到一個(gè)區(qū)域,而釋放另外一個(gè)區(qū)域;和整理方法一樣,也不會(huì)產(chǎn)生內(nèi)存碎片,并且復(fù)制和標(biāo)記可以同時(shí)進(jìn)行,但是需要更多的內(nèi)存區(qū)域。

JVM有多種垃圾收集器可供選擇,需要根據(jù)業(yè)務(wù)需求(低延遲or高吞吐)進(jìn)行權(quán)衡,CMS和G1使用相對(duì)較多。

a.?CMS用于老年代的垃圾回收,追求最短停頓;

b.?G1老年代和新生代都可以使用,并且相對(duì)高效;

c.?Java11 推出的Z Garbage Collector(ZGC)有著不錯(cuò)的性能,目前基本可以投入生產(chǎn)。

(https://docs.oracle.com/en/java/javase/11/gctuning/z-garbage-collector1.html)

1.3 Objective-C/Swift

Objective-C?是基于C語(yǔ)言發(fā)展出的面向?qū)ο蟮拈_發(fā)語(yǔ)言(Objective);Objective-C的語(yǔ)法相對(duì)繁瑣、不夠便捷,所以蘋果在2014推出了Swift,擁有腳本語(yǔ)言般的表現(xiàn)力。

Objective-C 的內(nèi)存管理基于簡(jiǎn)單的引用計(jì)數(shù),

可以分為兩類:

??MRR:Manual Retain-Release

(圖4 Objective-C MRR機(jī)制)

? ARC:Automatic Reference Counting

ARC底層還是MRR,只是由編譯器在恰當(dāng)?shù)奈恢脦臀覀儾迦雛etain和release。是否開啟ARC支持和編譯器版本以及編譯器選項(xiàng)有關(guān)。

1.4 Golang

Golang?也是具備垃圾回收的一種語(yǔ)言,主要應(yīng)用在后端開發(fā)領(lǐng)域;回收策略也是基于可達(dá)對(duì)象分析和標(biāo)記-清除-整理/復(fù)制算法。

和Java的比對(duì),可以參考以下鏈接:

https://blog.mooncascade.com/go-vs-java-we-chose-go-and-you-should-too/

02

引用模型對(duì)對(duì)象生命周期的影響

不同的引用類型對(duì)對(duì)象的生命周期影響不一樣,從語(yǔ)義上可分為三類:

??強(qiáng)引用(Strong reference)

- 強(qiáng)引用對(duì)象,不可以被回收

-?如果是基于引用計(jì)數(shù),引用計(jì)數(shù)會(huì)被影響

??軟引用(Soft reference)

-?非必要不回收,比如JVM在OOM之前會(huì)嘗試對(duì)Soft reference對(duì)象進(jìn)行回收

-?如果基于引用計(jì)數(shù),會(huì)退化為弱引用

??弱引用(Weak reference)??

-?不影響對(duì)象生命期

-?如果基于引用計(jì)數(shù),不會(huì)影響引用計(jì)數(shù)

03

C++的內(nèi)存管理方案

原則:盡量使用智能指針,不要擔(dān)心智能指針帶來(lái)性能損耗。

3.1 手動(dòng)管理內(nèi)存

在某些場(chǎng)景下,C++需要手動(dòng)管理內(nèi)存;我們可以使用一些技巧來(lái)更安全地使用和管理內(nèi)存。

a.?避免懸空指針

(點(diǎn)擊查看大圖)

b.?基于Allocator 策略進(jìn)行內(nèi)存分配

-?通過Allocator可以改變stl容器的內(nèi)存分配機(jī)制,比如為vector在棧上分配內(nèi)存;或者使用內(nèi)存池進(jìn)行內(nèi)存管理;

(點(diǎn)擊查看大圖)

3.2?COM 接口式內(nèi)存管理

COM (Component Object Model)是微軟在1993年提出的一種二進(jìn)制兼容的方案或者標(biāo)準(zhǔn),其中的思想還是挺值得插件開發(fā)借鑒(非windows平臺(tái))。

3.2.1 使用COM接口的優(yōu)勢(shì)

(一)COM接口可以解決插件開發(fā)領(lǐng)域的兩個(gè)典型的兼容問題

a.?接口的內(nèi)存布局結(jié)構(gòu)變化帶來(lái)的兼容問題

(圖5 接口的內(nèi)存布局變化導(dǎo)致的兼容問題)

b.?不同的編譯器、不同系統(tǒng)源碼庫(kù)帶來(lái)的兼容問題

(圖6 內(nèi)存管理不同版本帶來(lái)的兼容問題)

(二)COM接口為什么可以解決上述的問題?

a.?COM強(qiáng)調(diào)面向接口,插件的邊界只能是interface,COM接口不允許有任何的數(shù)據(jù)域

(圖7 COM嚴(yán)格以接口為邊界)

b.?COM接口需要暴露AddRef和Release接口,用來(lái)進(jìn)行閉環(huán)(插件申請(qǐng)插件釋放)的內(nèi)存管理

3.2.2 COM接口例子

? 場(chǎng)景:

?Application需要一個(gè)插件來(lái)提供讀和寫的功能

??原則:

所有的接口都要繼承?IUnknown?,發(fā)布的interface都需要有唯一ID

? DEMO:

a.?com.h

(點(diǎn)擊查看大圖)

b.?interface.h 插件對(duì)外發(fā)布的接口

(點(diǎn)擊查看大圖)

c.?export_api.h ?是插件的唯一接口暴露點(diǎn)

(點(diǎn)擊查看大圖)

d.?interface_impl.cpp 插件的功能實(shí)現(xiàn),可以使用繼承,也可以使用聚合的方法

?

(點(diǎn)擊查看大圖)

e.?插件的使用

(點(diǎn)擊查看大圖)

? Output:

(點(diǎn)擊查看大圖)

3.3 C++ 智能指針

C++11的很多特性都是先從boost引入技術(shù)報(bào)告(TR),然后進(jìn)入到C++標(biāo)準(zhǔn),智能指針就是如此。

(圖8 C++標(biāo)準(zhǔn)演進(jìn))

不同類型智能指針的比較:

(點(diǎn)擊查看大圖)

3.3.1?shared_ptr

shared_ptr是使用最廣泛的智能指針,可以進(jìn)行所有權(quán)共享;當(dāng)沒有任何人持有,引用計(jì)數(shù)為0的時(shí)候內(nèi)存自動(dòng)釋放。

智能指針內(nèi)部有兩個(gè)重要的塊:

a.??數(shù)據(jù)塊?指向內(nèi)存地址的指針

b.??控制塊?存放引用計(jì)數(shù)等信息

(圖9 shared_ptr原理)

3.3.2 weak_ptr

weak_ptr是shared_ptr的伴生品,weak_ptr沒有獨(dú)立存在意義。

(圖10 weak_ptr和shared_ptr的關(guān)系)

weak_ptr 可以解決share_ptr在兩個(gè)場(chǎng)景下的問題:

a. shared_ptr的循環(huán)引用,會(huì)造成內(nèi)存泄露

b. 觀察者模式 被觀察對(duì)象subject不應(yīng)該影響observer的生命周期

(點(diǎn)擊查看大圖)

Output:

(點(diǎn)擊查看大圖)

3.3.3?unique_ptr

unique_ptr 指向?qū)ο蟮乃袡?quán)獨(dú)享,在出作用域unique_ptr析構(gòu)時(shí)釋放內(nèi)存(和boost::scoped_ptr類似)。

如果要轉(zhuǎn)移所有權(quán),需要使用std::move。(類似的有std::thread,所有權(quán)獨(dú)占)

(圖11 unique_ptr的所有權(quán)轉(zhuǎn)移)

3.3.4?intrusive_ptr

侵入式(智能)指針,和share_ptr用起來(lái)很像。intrusive_ptr提供了自定義引用計(jì)數(shù)的能力,適合用來(lái)管理第三方接口。比如用intrusive_ptr來(lái)管理COM接口。

只需要實(shí)現(xiàn)?IUnknown?類型的?intrusive_ptr_add_ref?和?intrusive_ptr_release?方法,就可以像share_ptr一樣來(lái)使用COM接口了。

(點(diǎn)擊查看大圖)

Output:

(點(diǎn)擊查看大圖)

3.3.5?utilities

a.?使用make_shared/make_unique構(gòu)造智能指針,減少構(gòu)造性能損耗;(https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared)

b.?owner-based (as opposed to value-based) order??(https://en.cppreference.com/w/cpp/memory/shared_ptr/owner_before)

??owner-based order?

可以看作為控制塊的比較,看受智能指針影響生命期的對(duì)象是不是一個(gè);

??value-based order

可以看作數(shù)據(jù)塊的比較,比較內(nèi)存地址

(點(diǎn)擊查看大圖)

Output:

(點(diǎn)擊查看大圖)

c.?shared_from_this

??使用場(chǎng)景:

一個(gè)被智能指針管理的對(duì)象(class A的對(duì)象),在對(duì)象的內(nèi)部,又要調(diào)用一個(gè)使用std::shared_ptr的函數(shù)。

??網(wǎng)絡(luò)場(chǎng)景示例:

connection表示一個(gè)鏈接,連接成功之后,在?run?函數(shù)內(nèi)部調(diào)用?async_run?,實(shí)現(xiàn)異步讀操作;這個(gè)時(shí)候需要把自己的智能指針傳遞進(jìn)去,從而進(jìn)行生命期的托管。

(點(diǎn)擊查看大圖)

模擬一個(gè)網(wǎng)絡(luò)連接產(chǎn)生

(點(diǎn)擊查看大圖)

測(cè)試

(點(diǎn)擊查看大圖)

即使馬上將connection變量釋放,出了作用域之后,我們?nèi)匀豢梢赃M(jìn)行read操作。

-?例子使用的Thread pool

(點(diǎn)擊查看大圖)

std::enable_shared_from_this本質(zhì)上是一個(gè)語(yǔ)法糖,在基類中使用weak_ptr來(lái)幫我們避免了循環(huán)引用(自己引用自己)。

(點(diǎn)擊查看大圖)

謝謝觀看!

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

網(wǎng)站標(biāo)題:DeepRouteLab|C++內(nèi)存管理介紹-創(chuàng)新互聯(lián)
瀏覽路徑:http://aaarwkj.com/article18/ccosdp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、網(wǎng)站導(dǎo)航、App開發(fā)、網(wǎng)站設(shè)計(jì)公司、企業(yè)建站、建站公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
国产龙熟女高潮一区二区| 国产探花猛操性感美女| 日本五十路亲子在线一区| 在线观看午夜视频免费| 久久久久久97精品| 国产一区二区三区午夜视频| 亚洲人妻在线一区二区三区| 欧美一区二区三区人妻激情| 91亚洲精品一区二区三区| 人妻乱人伦中文字幕在线| 一区二区久久精品视频| 欧美日韩视频一区二区| 美女高潮呻吟免费观看久久久| 亚洲少妇精品视频在线| 日韩有码高清av在线| 国产日韩欧美 一区二区三区| 国产亚洲精品视频中文字幕| 亚洲欧美精品综合久久99| 国产交换精品一区二区三区| 亚洲成人大片免费在线观看 | 人妻有码av中文字幕久久| 日韩x级av免费在线观看| 欧美日韩在线一区2区| 成人福利网站午夜一区| 日韩色图在线观看视频| 午夜少妇诱惑一区二区三区| 国产精品六区久久综合亚洲av| 国产亚洲欧美日韩网站| 精品视频美女肉体亚洲| 亚洲三级av在线播放| 粉嫩一区二区三区精品视频| 精品欧美激情精品一区| 精品女同一区二区三区网站| 免费高清av一区二区| 亚洲综合色一区二区三区四区 | 欧美亚洲精品一区二区三区| 精品人妻aⅴ一区二区| 日韩精品在线观看一| 中文日本强暴人妻另类视频| 日韩av亚洲一区二区三区| 国产国产成年年人免费看片|