Python 採用引用計數的方式來管理分配的內存。Python 的每個對象都有一個引用計數,這個引用計數表明了有多少對象在指向它。當這個引用計數爲 0 時,釋放該對象的內存。爲了解決循環引用的問題,Python提供了“標記-清除”法,用於釋放循環引用的對象。
爲了加速Python的執行效率,Python 同時使用了一個內存池機制,用於管理對小塊內存的申請和釋放。 Python 的垃圾收集並不會把不用的內存返回給操作系統,而是放到了內存池。對於 int, float, list 對象, Python 還提供了獨立的私有內存池。
Python 通過引用計數來確定當前變量是否需要釋放。每個對象都有一個計數器,當一個對象的引用計數爲0時,就會由 gc 模塊來執行內存釋放操作。假如這個對象在緩衝區內,那麼它地址空間不會被釋放,而是等待下一次被使用,而非緩衝區的該釋放就釋放。
對於普通對象 gc 採取分代回收算法,對象根據存活的時間分爲三“代”,所有新建的對象都是0代,當0代對象經過一次自動垃圾回收,沒有被釋放的對象會被歸入1代,同理1代歸入2代。
對於因循環引用而無法釋放的對象,Python 採用“標記-清除”法。
Python 下造成內存泄漏的原因大概有這幾方面:
- 對象一直被全局變量所引用, 全局變量生命週期長.
- 垃圾回收機被禁用或者設置成debug狀態, 垃圾回收的內存不會被釋放.
- 循環引用過多, gc 無法及時釋放