彻底理解内存泄漏,memory leak
作者 | 碼農的荒島求生
來源 | 碼農的荒島求生
內存申請就好比去停車場找停車位,找到停車位后你就可以把車停在這里。
從這個類比看什么是內存泄漏呢?內存泄漏看上去是停車場的車輛只進不出導致最終找不到停車位,從程序員的角度看就是內存只申請取不釋放,如果你去問,可能有不少人認為內存泄漏就是這么回事。
然而這其實是不全面的。
申請過多內存
首先內存只申請不釋放未必就是內存泄漏,有可能是你的程序的確需要申請很多內存,這是正常的,然而如果是bug導致申請了很多內存,這就是內存泄漏了,或者也有人將其稱為space leak,意思是申請的內存超過了正常所需;不管是有意無意,總之在這種情況下你依然保持對這些內存的引用,因此你總可以找到這些內存并刪除它們,就看你刪不刪。
有很多情況會導致這一問題,像重復使用的某個結構體/對象,當再次復用時沒有清理上一次使用遺留的數據、系統中存在cache,但cache的過期策略設置不得當等等。
內存無法刪除
另一類比較有趣的內存泄漏是說你申請了一些內存,但最終卻沒有什么指向它們:
void memory_leak() {char* mem = (char*)malloc(1024);// just return }在這段代碼中我們申請了1k內存,然而當memory_leak函數返回后你就再也不知道這段內存到底在哪里了!
用停車場的示例來說就是有些司機太過土豪,家里的車太多以至于把將車放在停車場這件事忘掉了,導致這些車根本就不會有人再開走,因此白白浪費停車位,并導致可用車位越來越少,而對于編程來說就是粗心大意的程序員申請了一些內存后最終“忘掉”了,再也不會有什么東西(變量/指針)指向這些內存,因此在這種情況下你沒有辦法再找到這些內存并將其刪除。
內存碎片
這也算的上是一類特殊的內存泄漏,用停車場的例子來說就是兩個停車位中間停靠了一輛小型老年代步車,導致盡管這兩個停車位剩余的空間足夠大但又恰好都沒有辦法再停靠一輛小汽車。
假定我們系統中寶貴的內存大小只有8字節,其中有兩個字節已經分配出去了,就像這樣:
現在,系統中空閑的內存是6字節,下一次的內存申請需要分配5字節,糟糕,我們已經沒有辦法再找到連續的5個字節大小的內存空間了,盡管全部空間的內存還有6字節,這就是所謂的內存碎片問題。
而對于內存分配器來說如果出現這種情況那么將不得不借助操作系統的幫助來擴大堆區,因此看起來我們的程序占據的內存越來越多,盡管實際上程序可能并不需要那么多內存,僅僅是因為內存碎片的原因導致一部分內存無法被再次被利用起來。
然而對于現代操作系統尤其具備虛擬內存能力的系統來說,內存碎片問題通常可能并不會和我們想象的那樣嚴重,原因就在于分配的內存只需要在虛擬地址空間上連續而不必在物理內存上也連續,假定我們在虛擬內存地址空間需要存放“aabbccdd”這樣的字符串,在虛擬地址空間上看這是連續的就像這樣:
但在物理內存上可能是這樣存放的:
可以看到,利用虛擬內存我們可以更加充分靈活的利用“邊邊角角”的物理內存,從而減少內存碎片帶來的影響。
如果你的程序需要重復申請很多對象/數據/結構體,并在最后一次性全部釋放,那么內存池是一個避免內存碎片不錯的選擇,原理在于盡管從內存池的角度看會有碎片,但當我們以內存池大小為單位從堆區中申請釋放內存時,這種碎片將不復存在。
內存泄漏帶來的問題
在現代操作系統中除非你的程序運行時間足夠長或者申請的內存足夠快足夠多否則內存泄漏可能并不是什么大問題,你甚至可能都察覺不出來有內存泄漏,因為當進程運行結束后其占據的內存會被操作系統收回,在這種情況下你可能不必過于關心這個問題,但對于長時間運行的服務器端程序、數據庫程序、操作系統等,內存泄漏就屬于比較嚴重的問題了,因為這些程序必須時刻在線,任何微小的內存泄漏在時間的加持下都會非常明顯。
內存持續泄漏會發生什么?
如果內存持續泄漏那么你的電腦可能會爆炸。。。這。。。當然是不可能的。
你的系統會慢到炸是有可能的。
內存的申請速度會對系統性能產生很大的影響,當系統內存不足時,內存分配器找到一塊滿足要求的空閑內存塊將更加困難耗時更多,當程序消耗的內存超過物理內存大小時虛擬內存系統(如果有的話)開始發揮作用,將進程地址空間中不常用的一部分swap出去,此時系統性能將快速下降,表現出來的就是程序員運行變慢、卡頓。
當然,根據系統配置,像Linux系統,可能會將消耗內存很多的進程kill掉,這就是Out of Memory killer,簡稱oom killer。
內存泄漏檢測工具
不像程序崩潰Core dump,這類問題通過debug通常能獲取一些線索,但內存泄漏問題就沒那么直接了,尤其對于C/C++程序來說,這時我們將不得不借助必要的工具。
往期推薦
虛幻引擎5上的《黑客帝國》全新體驗,愛了愛了
低代碼發展專訪系列之七:低代碼的火爆需要不一樣的聲音么?
Log4j 第三次發布漏洞補丁,漏洞或將長存
5G專網,路在何方?
點分享
點收藏
點點贊
點在看
總結
以上是生活随笔為你收集整理的彻底理解内存泄漏,memory leak的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 明明还有大量内存,为啥报错“无法分配内存
- 下一篇: 为什么服务端程序都需要先 listen