一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - C/C++ - 淺談QT內(nèi)存泄漏

淺談QT內(nèi)存泄漏

2022-01-11 14:56yhl_sophia C/C++

本文主要介紹了淺談QT內(nèi)存泄漏,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

 

01前言

   前幾天,項(xiàng)目開展了一次代碼初次評(píng)審。會(huì)上,領(lǐng)導(dǎo)指出一些可能會(huì)帶來內(nèi)存泄漏的代碼,如下圖所示:

淺談QT內(nèi)存泄漏

圖中的pLayout在new的時(shí)候沒有指定任何父對(duì)象,且MainWindow的析構(gòu)函數(shù)中也沒有對(duì)pLayout做delete操作,這意味著為pLayout申請(qǐng)的內(nèi)存空間在程序運(yùn)行期間是一直沒有得到釋放的。實(shí)際上,項(xiàng)目代碼中,還有許多這種“隱患”:一個(gè)單例類的成員變量在new的時(shí)候沒有指定父對(duì)象、一個(gè)靜態(tài)類的成員在new的時(shí)候沒有指定父對(duì)象……

這些“隱患”為何在目前程序運(yùn)行時(shí)沒有暴露出問題?基于這個(gè)疑惑,我研究了QT的半自動(dòng)化的內(nèi)存管理,并結(jié)合實(shí)驗(yàn)進(jìn)行結(jié)果驗(yàn)證,現(xiàn)將分析過程記錄下來

 

02 QT半自動(dòng)化內(nèi)存管理要點(diǎn)

  • QObject及其派生類的對(duì)象,如果其parent非0,那么其parent析構(gòu)時(shí)會(huì)析構(gòu)該對(duì)象
  • QWidget及其派生類的對(duì)象,可以設(shè)置 Qt::WA_DeleteOnClose 標(biāo)志位(當(dāng)close時(shí)會(huì)析構(gòu)該對(duì)象)
  • QAbstractAnimation派生類的對(duì)象,可以設(shè)置 QAbstractAnimation::DeleteWhenStopped
  • QRunnable::setAutoDelete()、MediaSource::setAutoDelete()
  • 父子關(guān)系:父對(duì)象、子對(duì)象、父子關(guān)系。這是Qt中所特有的,與類的繼承關(guān)系無關(guān),傳遞參數(shù)與parent有關(guān)(基類、派生類,或父類、子類,這是對(duì)于派生體系來說的,與parent無關(guān))

 

03實(shí)驗(yàn)過程詳解

堆空間的內(nèi)存泄漏與改進(jìn)方法實(shí)踐實(shí)例

繼承QWidget類的Test類,通過new為其分配內(nèi)存,沒有設(shè)置WA_DeleteOnclose屬性且使用完后也沒有delete

淺談QT內(nèi)存泄漏

淺談QT內(nèi)存泄漏

淺談QT內(nèi)存泄漏

實(shí)驗(yàn)結(jié)果:關(guān)閉testWidget窗口后,沒有調(diào)用其析構(gòu)函數(shù)打印“test delete”信息。直到程序結(jié)束之前testWidget的申請(qǐng)的內(nèi)存空間都未被釋放

改進(jìn)方法A

為testWidget窗口設(shè)置Qt::WA_DeleteOnClose屬性

淺談QT內(nèi)存泄漏

實(shí)驗(yàn)結(jié)果:關(guān)閉testWidget窗口后,調(diào)用了其析構(gòu)函數(shù),內(nèi)存被釋放了

改進(jìn)方法B

不設(shè)置Qt::WA_DeleteOnClose屬性,但是在new完testWidget后,程序退出前調(diào)用testWidget的delete函數(shù)

淺談QT內(nèi)存泄漏

淺談QT內(nèi)存泄漏

實(shí)驗(yàn)結(jié)果:關(guān)閉testWidget窗口后,調(diào)用了其析構(gòu)函數(shù),內(nèi)存也被釋放了

實(shí)驗(yàn)結(jié)論:QWidget及其派生類的對(duì)象,可以設(shè)置 Qt::WA_DeleteOnClose 標(biāo)志位(當(dāng)close時(shí)會(huì)析構(gòu)該對(duì)象)或者手動(dòng)delete來釋放內(nèi)存

棧空間的內(nèi)存實(shí)踐實(shí)例不采用new,為testWidget分配棧空間,不設(shè)置Qt::WA_DeleteOnClose屬性,不手動(dòng)delete

淺談QT內(nèi)存泄漏

淺談QT內(nèi)存泄漏

實(shí)驗(yàn)結(jié)果:關(guān)閉窗口時(shí)調(diào)用了testWidget的析構(gòu)函數(shù),內(nèi)存被釋放了

testWidget不采用new創(chuàng)建,直接將對(duì)象建議在棧空間,但設(shè)置Qt::WA_DeleteOnClose屬性或者使用后delete &testWidget

淺談QT內(nèi)存泄漏

淺談QT內(nèi)存泄漏

實(shí)驗(yàn)結(jié)果:程序崩潰了,在第一次嘗試delete testWidget時(shí)就出錯(cuò)

淺談QT內(nèi)存泄漏

實(shí)驗(yàn)結(jié)論:delete棧上分配的地址會(huì)出錯(cuò)

父對(duì)象和子對(duì)象析構(gòu)的實(shí)踐實(shí)例將testWidget的父對(duì)象設(shè)置為mainwindow

淺談QT內(nèi)存泄漏

實(shí)驗(yàn)結(jié)果:關(guān)閉窗口后,正常打印析構(gòu)信息。程序退出前,先釋放testWidget的空間,再釋放mainwindow的空間(兩者都是分配到棧空間)

淺談QT內(nèi)存泄漏

調(diào)整mainwindow和testWidget的構(gòu)造順序

淺談QT內(nèi)存泄漏

實(shí)驗(yàn)結(jié)果:程序崩潰

分析原因:mainwindow析構(gòu)時(shí)會(huì)將其子對(duì)象testWidget也析構(gòu),但testWidget是分配到棧空間上的,delete棧上的空間會(huì)出錯(cuò)。

淺談QT內(nèi)存泄漏

將testWidget分配到堆上,指定父對(duì)象為mainwindow,并在程序退出前delete mainwindow

淺談QT內(nèi)存泄漏

實(shí)驗(yàn)結(jié)果:delete mainwindow時(shí),會(huì)將testWidget也一并delete

淺談QT內(nèi)存泄漏

將testWidget作為mainwindow的成員,但在構(gòu)造時(shí)不指定父對(duì)象,在main函數(shù)中delete mainwindow

淺談QT內(nèi)存泄漏

淺談QT內(nèi)存泄漏

實(shí)驗(yàn)結(jié)果:應(yīng)用程序退出前只有mainwindow被析構(gòu)了

淺談QT內(nèi)存泄漏

實(shí)驗(yàn)結(jié)論:

  • 析構(gòu)函數(shù)總是出現(xiàn)在對(duì)象的生命期結(jié)束之時(shí),靜態(tài)對(duì)象在程序運(yùn)行結(jié)束之時(shí)析構(gòu)。
  • 對(duì)象的構(gòu)造和析構(gòu)的關(guān)系是棧數(shù)據(jù)結(jié)構(gòu)中的入棧和出棧的關(guān)系。
  • 指定了父對(duì)象的子對(duì)象,在父對(duì)象被析構(gòu)時(shí),會(huì)將其一并析構(gòu)掉

 

Malloc分配的內(nèi)存空間實(shí)踐實(shí)例

新建一個(gè)malloc_class,將malloc_class作為mainwindow的成員,在mallocClass的構(gòu)造函數(shù)里面用malloc申請(qǐng)500M內(nèi)存,在mainwindow放置一個(gè)button,點(diǎn)擊button就delete malloc_class,在任務(wù)管理器中看500M內(nèi)存是否有被釋放。對(duì)于malloc_class的new操作,測(cè)試了兩種情況:

new malloc_class時(shí)不指定父對(duì)象new malloc_class時(shí)指定它的父對(duì)象為mainwindow

淺談QT內(nèi)存泄漏

淺談QT內(nèi)存泄漏

實(shí)驗(yàn)結(jié)果:兩種情況一樣的結(jié)果,點(diǎn)擊button,在delete testWidget后,在testThread中申請(qǐng)的500M空間都沒有被釋放

淺談QT內(nèi)存泄漏

淺談QT內(nèi)存泄漏

猜想是不是因?yàn)閙alloc的空間并沒有指定父對(duì)象,異想天開的又測(cè)試了另外一種情況:直接創(chuàng)建malloc_class時(shí)用malloc為其分配內(nèi)存,再在button的槽函數(shù)里delete malloc_class

淺談QT內(nèi)存泄漏

實(shí)驗(yàn)結(jié)果:程序崩潰了……

淺談QT內(nèi)存泄漏

查閱資料得知:malloc只能為POD類型數(shù)據(jù)(一個(gè)類或結(jié)構(gòu)體通過二進(jìn)制拷貝后還能保持?jǐn)?shù)據(jù)不變,具體解釋自查資料)分配內(nèi)存,其他的必須用new分配內(nèi)存。Malloc函數(shù)分配內(nèi)存空間時(shí)并不調(diào)用構(gòu)造函數(shù),同樣free函數(shù)再回收空間時(shí)也不調(diào)用析構(gòu)函數(shù)。

實(shí)驗(yàn)結(jié)論:malloc分配的內(nèi)存空間都要自己管理,與QT的父子對(duì)象同步析構(gòu)沒有關(guān)系。也就是說應(yīng)該再次明確:指定父對(duì)象的并且基于QObject為基類的對(duì)象才會(huì)同步析構(gòu)

注意:malloc的空間只是一個(gè)虛擬內(nèi)存,一定要初始化或者寫數(shù)據(jù)才會(huì)有物理內(nèi)存的體現(xiàn)

 

04總結(jié)

對(duì)于在應(yīng)用程序中不是常駐的對(duì)象,應(yīng)習(xí)慣為其指定父對(duì)象,或著用完之后手動(dòng)delete;對(duì)于應(yīng)用程序中常駐的對(duì)象,即便在應(yīng)用程序結(jié)束后操作系統(tǒng)會(huì)釋放其使用的內(nèi)存,也不建議隨性new沒有parent的對(duì)象。總之,養(yǎng)成嚴(yán)格處理內(nèi)存分配和釋放內(nèi)存的好習(xí)慣,要清楚自己在編碼時(shí)使用了哪些內(nèi)存,什么時(shí)候需要釋放,不定時(shí)關(guān)注程序的內(nèi)存占用率。

到此這篇關(guān)于淺談QT內(nèi)存泄漏的文章就介紹到這了,更多相關(guān)QT內(nèi)存泄漏內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://blog.csdn.net/yhl_sophia/article/details/120408826

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 青春草视频在线免费观看 | 欧美日韩国产亚洲一区二区三区 | 丰满的闺蜜2中文字幕 | japaneseles女同专区 | 色色色色网站 | 亚洲国产99| 日本漫画工囗全彩番在线 | 色综合综合 | 摸咪网在线影院在线观看 | 门房秦大爷最新章节阅读 | 爱欲荡漾在线观看 | 日韩精品一区二区三区中文字幕 | 91国产在线观看 | 亚洲网站在线观看 | 青青青青青国产费线在线观看 | 国产精品久久久久久久久 | 欧美男男gaygayxxx| 青柠影院在线观看免费完整版1 | 明星ai人脸替换脸忘忧草 | 深夜视频在线播放 | 欧美国产在线视频 | 欧美a在线 | 午夜视频一区二区 | 日本b站一卡二不卡三卡四卡 | 日本韩国推理片免费观看网站 | 嫩草影院永久在线播放 | 动漫美女人物被黄漫在线看 | 国产一区二区免费不卡在线播放 | 国产精品天天影视久久综合网 | 99er热| 欧美一区二区三区久久久 | 欧美坐爱 | 好大好硬快点好爽公 | 国产性做久久久久久 | 波多 在线播放 | 国产亚洲精品一区二区在线播放 | 国产精品污双胞胎在线观看 | 亚洲精品国产AV成人毛片 | 男女男在线精品网站免费观看 | 色小孩导航 | 色婷婷天天综合在线 |