最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

源碼解析python的內(nèi)存回收機(jī)制

 更新時(shí)間:2023年04月21日 10:06:22   作者:菜鳥小超  
在CPython中,引用計(jì)數(shù)是用來(lái)管理內(nèi)存的一種方法,當(dāng)一個(gè)Python對(duì)象的引用計(jì)數(shù)變?yōu)榱銜r(shí),表示沒(méi)有其他對(duì)象引用該對(duì)象,因此可以安全地將其內(nèi)存回收,需要的朋友可以參考下

一:建立對(duì)象引用計(jì)數(shù)

1. 相關(guān)代碼

void
_Py_NewReference(PyObject *op)
{
    if (_Py_tracemalloc_config.tracing) {
        _PyTraceMalloc_NewReference(op);
    }
#ifdef Py_REF_DEBUG
    _Py_RefTotal++;
#endif
    Py_SET_REFCNT(op, 1);
#ifdef Py_TRACE_REFS
    _Py_AddToAllObjects(op, 1);
#endif
}

2. 代碼解釋

_Py_NewReference這個(gè)函數(shù)的主要目的是為新創(chuàng)建的Python對(duì)象建立引用計(jì)數(shù)。在CPython中,引用計(jì)數(shù)是用來(lái)管理內(nèi)存的一種方法,當(dāng)一個(gè)Python對(duì)象的引用計(jì)數(shù)變?yōu)榱銜r(shí),表示沒(méi)有其他對(duì)象引用該對(duì)象,因此可以安全地將其內(nèi)存回收。

下面是_Py_NewReference函數(shù)的各個(gè)部分的簡(jiǎn)要說(shuō)明:

  1. _Py_tracemalloc_config.tracing:當(dāng)內(nèi)存追蹤功能啟用時(shí)(即_Py_tracemalloc_config.tracing為真),調(diào)用_PyTraceMalloc_NewReference(op)以記錄新引用的內(nèi)存分配。
  2. #ifdef Py_REF_DEBUG:如果啟用了引用計(jì)數(shù)調(diào)試(即編譯時(shí)定義了Py_REF_DEBUG),則增加全局引用計(jì)數(shù)_Py_RefTotal。
  3. Py_SET_REFCNT(op, 1):將新對(duì)象op的引用計(jì)數(shù)設(shè)置為1。
  4. #ifdef Py_TRACE_REFS:如果啟用了引用跟蹤功能(即編譯時(shí)定義了Py_TRACE_REFS),則調(diào)用_Py_AddToAllObjects(op, 1)將新對(duì)象op添加到所有對(duì)象列表中以進(jìn)行跟蹤。

這個(gè)函數(shù)通常在創(chuàng)建新的Python對(duì)象時(shí)調(diào)用,以便正確初始化引用計(jì)數(shù)。需要注意的是,這個(gè)函數(shù)是CPython內(nèi)部使用的,不應(yīng)該在普通Python代碼或擴(kuò)展模塊中直接使用。

#ifdef Py_REF_DEBUG是一個(gè)C預(yù)處理器指令,它會(huì)檢查是否在編譯時(shí)定義了Py_REF_DEBUG宏。如果定義了這個(gè)宏,那么在#ifdef#endif之間的代碼塊將被編譯并包含在最終的程序中。否則,這部分代碼將被忽略。

Py_REF_DEBUG宏用于啟用引用計(jì)數(shù)調(diào)試功能。這個(gè)功能允許CPython開發(fā)者和擴(kuò)展模塊開發(fā)者在開發(fā)過(guò)程中更輕松地追蹤和診斷潛在的引用計(jì)數(shù)錯(cuò)誤。這對(duì)于調(diào)試內(nèi)存泄漏或提前釋放對(duì)象等問(wèn)題非常有用。

當(dāng)啟用Py_REF_DEBUG時(shí),_Py_RefTotal變量被用來(lái)跟蹤當(dāng)前分配給Python對(duì)象的總引用計(jì)數(shù)。這個(gè)全局計(jì)數(shù)器在每次創(chuàng)建新引用(如在_Py_NewReference函數(shù)中)時(shí)遞增,在釋放引用時(shí)遞減。通過(guò)檢查_Py_RefTotal的值,開發(fā)者可以在某些情況下發(fā)現(xiàn)可能的內(nèi)存泄漏或錯(cuò)誤的引用計(jì)數(shù)操作。

需要注意的是,Py_REF_DEBUG功能會(huì)帶來(lái)一定的性能開銷,因此在生產(chǎn)環(huán)境中通常不啟用。在發(fā)布構(gòu)建中,默認(rèn)情況下不會(huì)定義Py_REF_DEBUG宏。在開發(fā)和調(diào)試階段,可以通過(guò)配置構(gòu)建選項(xiàng)來(lái)啟用這個(gè)功能。

二: 引用計(jì)數(shù)增加

1. 相關(guān)源碼

// 引用計(jì)數(shù)增加
void
Py_IncRef(PyObject *o)
{
    Py_XINCREF(o);
}

// 宏定義
#define Py_XINCREF(op) _Py_XINCREF(_PyObject_CAST(op))

// 內(nèi)聯(lián)函數(shù)
static inline void _Py_XINCREF(PyObject *op)
{
    if (op != NULL) {
        Py_INCREF(op);
    }
}

// 宏定義
#define Py_INCREF(op) _Py_INCREF(_PyObject_CAST(op))

static inline void _Py_INCREF(PyObject *op)
{
#ifdef Py_REF_DEBUG
    _Py_RefTotal++;
#endif
    op->ob_refcnt++;  // 對(duì)象的引用計(jì)數(shù)加1
}

2. 源碼解釋

_Py_INCREF函數(shù)是一個(gè)靜態(tài)內(nèi)聯(lián)函數(shù),用于增加給定Python對(duì)象(op)的引用計(jì)數(shù)。內(nèi)聯(lián)函數(shù)允許編譯器在調(diào)用處內(nèi)聯(lián)展開函數(shù)體,以減少函數(shù)調(diào)用的開銷。以下是_Py_INCREF函數(shù)的各個(gè)部分的簡(jiǎn)要說(shuō)明:

#ifdef Py_REF_DEBUG:如果啟用了引用計(jì)數(shù)調(diào)試(即編譯時(shí)定義了Py_REF_DEBUG),則增加全局引用計(jì)數(shù)_Py_RefTotal。op->ob_refcnt++:增加給定Python對(duì)象op的引用計(jì)數(shù)(ob_refcnt字段)。

Py_INCREF是一個(gè)宏,用于調(diào)用_Py_INCREF函數(shù)。在調(diào)用_Py_INCREF之前,它首先使用_PyObject_CAST宏將給定的對(duì)象(op)轉(zhuǎn)換為PyObject指針。這是為了確保_Py_INCREF函數(shù)接收到的參數(shù)具有正確的類型。在編寫Python C擴(kuò)展時(shí),通常會(huì)使用Py_INCREF宏來(lái)增加Python對(duì)象的引用計(jì)數(shù)。

三:引用計(jì)數(shù)減少

1. 相關(guān)源碼

void
Py_DecRef(PyObject *o)
{
    Py_XDECREF(o);
}

#define Py_XDECREF(op) _Py_XDECREF(_PyObject_CAST(op))

static inline void _Py_XDECREF(PyObject *op)
{
    if (op != NULL) {
        Py_DECREF(op);
    }
}

define Py_DECREF(op) _Py_DECREF(_PyObject_CAST(op))

static inline void _Py_DECREF(
#ifdef Py_REF_DEBUG
    const char *filename, int lineno,
#endif
    PyObject *op)
{
#ifdef Py_REF_DEBUG
    _Py_RefTotal--;
#endif
    if (--op->ob_refcnt != 0) {
#ifdef Py_REF_DEBUG
        if (op->ob_refcnt < 0) {
            _Py_NegativeRefcount(filename, lineno, op);
        }
#endif
    }
    else {
        _Py_Dealloc(op);
    }
}

// 引用計(jì)數(shù)等于0了,就調(diào)用dealloc函數(shù)進(jìn)行對(duì)象刪除
void
_Py_Dealloc(PyObject *op)
{
    destructor dealloc = Py_TYPE(op)->tp_dealloc;
#ifdef Py_TRACE_REFS
    _Py_ForgetReference(op);
#endif
    (*dealloc)(op);
}

2. 源碼解釋

在這段代碼中,我們可以看到Py_DecRef、Py_XDECREF、_Py_XDECREF、Py_DECREF_Py_DECREF這幾個(gè)用于處理Python對(duì)象引用計(jì)數(shù)的函數(shù)和宏。

  1. Py_DecRef:這是一個(gè)簡(jiǎn)單的封裝函數(shù),接受一個(gè)指向PyObject的指針o作為參數(shù),然后調(diào)用Py_XDECREF(o)宏。
  2. Py_XDECREF:這是一個(gè)宏,用于調(diào)用_Py_XDECREF函數(shù)。在調(diào)用之前,它使用_PyObject_CAST(op)宏將給定的對(duì)象(op)轉(zhuǎn)換為PyObject指針。
  3. _Py_XDECREF:這是一個(gè)靜態(tài)內(nèi)聯(lián)函數(shù),用于在給定對(duì)象不為NULL時(shí)調(diào)用Py_DECREF宏。這意味著如果對(duì)象指針為空(即op == NULL),則不會(huì)對(duì)引用計(jì)數(shù)進(jìn)行任何操作。
  4. Py_DECREF:這是一個(gè)宏,用于調(diào)用_Py_DECREF函數(shù)。在調(diào)用之前,它使用_PyObject_CAST(op)宏將給定的對(duì)象(op)轉(zhuǎn)換為PyObject指針。
  5. _Py_DECREF:這是一個(gè)靜態(tài)內(nèi)聯(lián)函數(shù),用于減少給定Python對(duì)象(op)的引用計(jì)數(shù)。以下是_Py_DECREF函數(shù)的各個(gè)部分的簡(jiǎn)要說(shuō)明:

a. #ifdef Py_REF_DEBUG:如果啟用了引用計(jì)數(shù)調(diào)試(即編譯時(shí)定義了Py_REF_DEBUG),則減少全局引用計(jì)數(shù)_Py_RefTotal。

b. 減少對(duì)象的引用計(jì)數(shù):使用--op->ob_refcnt來(lái)減少給定對(duì)象op的引用計(jì)數(shù)。

c. 判斷引用計(jì)數(shù)是否為0:如果引用計(jì)數(shù)不為0,表示仍有其他對(duì)象引用該對(duì)象。如果引用計(jì)數(shù)為0,則調(diào)用_Py_Dealloc(op)來(lái)釋放對(duì)象的內(nèi)存。在引用計(jì)數(shù)調(diào)試模式下,還會(huì)檢查引用計(jì)數(shù)是否為負(fù)數(shù),如果是,則調(diào)用_Py_NegativeRefcount(filename, lineno, op)報(bào)告錯(cuò)誤。

在Python C擴(kuò)展中,通常使用Py_DECREFPy_XDECREF宏來(lái)減少Python對(duì)象的引用計(jì)數(shù)。這些宏提供了安全和高效的方式來(lái)處理引用計(jì)數(shù),以防止內(nèi)存泄漏和提前釋放對(duì)象。

四:對(duì)象刪除

1. 相關(guān)源碼

void
_Py_Dealloc(PyObject *op)
{
    destructor dealloc = Py_TYPE(op)->tp_dealloc;
#ifdef Py_TRACE_REFS
    _Py_ForgetReference(op);
#endif
    (*dealloc)(op);
}

2. 源碼解釋

_Py_Dealloc函數(shù)是CPython中用于釋放Python對(duì)象內(nèi)存的函數(shù)。它在對(duì)象的引用計(jì)數(shù)變?yōu)榱銜r(shí)調(diào)用,表示沒(méi)有其他對(duì)象引用該對(duì)象,可以安全地回收其內(nèi)存。以下是_Py_Dealloc函數(shù)的各個(gè)部分的簡(jiǎn)要說(shuō)明:

destructor dealloc = Py_TYPE(op)->tp_dealloc;:從給定Python對(duì)象op的類型對(duì)象中獲取析構(gòu)函數(shù)(tp_dealloc),并將其賦值給dealloc。每個(gè)類型對(duì)象都有一個(gè)與之關(guān)聯(lián)的析構(gòu)函數(shù),該函數(shù)負(fù)責(zé)清理該類型的對(duì)象所占用的內(nèi)存。#ifdef Py_TRACE_REFS:如果啟用了引用跟蹤功能(即編譯時(shí)定義了Py_TRACE_REFS),則調(diào)用_Py_ForgetReference(op)將對(duì)象op從所有對(duì)象列表中刪除,以便不再跟蹤該對(duì)象。(*dealloc)(op);:調(diào)用dealloc指向的析構(gòu)函數(shù),釋放對(duì)象op所占用的內(nèi)存。這里使用了函數(shù)指針,這意味著dealloc可以指向任何類型的析構(gòu)函數(shù),從而可以靈活地處理不同類型的Python對(duì)象。

需要注意的是,_Py_Dealloc函數(shù)是CPython內(nèi)部使用的,不應(yīng)該在普通Python代碼或擴(kuò)展模塊中直接使用。在Python擴(kuò)展模塊中,您應(yīng)該使用相應(yīng)的宏和API函數(shù)來(lái)管理引用計(jì)數(shù),例如Py_DECREFPy_XDECREF。

Py_TYPE(op)是一個(gè)宏,用于獲取給定Python對(duì)象(op)的類型。它返回一個(gè)指向PyTypeObject結(jié)構(gòu)的指針,這個(gè)結(jié)構(gòu)包含了對(duì)象類型的相關(guān)信息,如類型名、方法、屬性、析構(gòu)函數(shù)等。

在CPython內(nèi)部實(shí)現(xiàn)中,每個(gè)Python對(duì)象都包含一個(gè)指向其類型對(duì)象的指針。這個(gè)指針位于PyObject結(jié)構(gòu)的ob_type字段中。Py_TYPE(op)宏實(shí)際上就是訪問(wèn)這個(gè)ob_type字段,即op->ob_type

在Python C擴(kuò)展和嵌入式代碼中,Py_TYPE(op)宏可以用于檢查對(duì)象的類型、獲取類型特定的函數(shù)或執(zhí)行類型相關(guān)的操作。例如,可以通過(guò)比較兩個(gè)對(duì)象的類型對(duì)象來(lái)判斷它們是否屬于相同的類型。

到此這篇關(guān)于源碼解析python的內(nèi)存回收機(jī)制的文章就介紹到這了,更多相關(guān)python的內(nèi)存回收機(jī)制解析內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Pygame游戲開發(fā)之太空射擊實(shí)戰(zhàn)子彈與碰撞處理篇

    Pygame游戲開發(fā)之太空射擊實(shí)戰(zhàn)子彈與碰撞處理篇

    相信大多數(shù)8090后都玩過(guò)太空射擊游戲,在過(guò)去游戲不多的年代太空射擊自然屬于經(jīng)典好玩的一款了,今天我們來(lái)自己動(dòng)手實(shí)現(xiàn)它,在編寫學(xué)習(xí)中回顧過(guò)往展望未來(lái),下面開始講解子彈與碰撞處理,在本課中,我們將添加玩家與敵人之間的碰撞,以及添加供玩家射擊的子彈
    2022-08-08
  • Python中g(shù)etattr函數(shù)和hasattr函數(shù)作用詳解

    Python中g(shù)etattr函數(shù)和hasattr函數(shù)作用詳解

    這篇文章主要介紹了Python中g(shù)etattr函數(shù)和hasattr函數(shù)作用的相關(guān)知識(shí),非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-06-06
  • 使用Flask和Django中解決跨域請(qǐng)求問(wèn)題

    使用Flask和Django中解決跨域請(qǐng)求問(wèn)題

    這篇文章主要介紹了使用Flask和Django中解決跨域請(qǐng)求問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • 淺談Python3多線程之間的執(zhí)行順序問(wèn)題

    淺談Python3多線程之間的執(zhí)行順序問(wèn)題

    這篇文章主要介紹了淺談Python3多線程之間的執(zhí)行順序問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-05-05
  • Python實(shí)現(xiàn)小黑屋游戲的完整實(shí)例

    Python實(shí)現(xiàn)小黑屋游戲的完整實(shí)例

    這篇文章主要給大家介紹了關(guān)于Python實(shí)現(xiàn)小黑屋游戲的完整實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Python 逐行分割大txt文件的方法

    Python 逐行分割大txt文件的方法

    本文通過(guò)代碼給大家介紹了Python 逐行分割大txt文件的方法,在文中給大家提到了Python從txt文件中逐行讀取數(shù)據(jù)的方法,需要的朋友參考下吧
    2017-10-10
  • sklearn-SVC實(shí)現(xiàn)與類參數(shù)詳解

    sklearn-SVC實(shí)現(xiàn)與類參數(shù)詳解

    今天小編就為大家分享一篇sklearn-SVC實(shí)現(xiàn)與類參數(shù)詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12
  • python實(shí)現(xiàn)打磚塊游戲

    python實(shí)現(xiàn)打磚塊游戲

    這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)打磚塊游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • python實(shí)現(xiàn)上傳樣本到virustotal并查詢掃描信息的方法

    python實(shí)現(xiàn)上傳樣本到virustotal并查詢掃描信息的方法

    這篇文章主要介紹了python實(shí)現(xiàn)上傳樣本到virustotal并查詢掃描信息的方法,是比較實(shí)用的技巧,需要的朋友可以參考下
    2014-10-10
  • 基于Python批量生成指定尺寸縮略圖代碼實(shí)例

    基于Python批量生成指定尺寸縮略圖代碼實(shí)例

    這篇文章主要介紹了基于Python批量生成指定尺寸縮略圖代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11

最新評(píng)論

房山区| 通江县| 陇南市| 莲花县| 芒康县| 通州区| 甘德县| 轮台县| 泾阳县| 南溪县| 资中县| 虞城县| 盐城市| 抚顺县| 吉木萨尔县| 海城市| 富源县| 金乡县| 白沙| 泸州市| 桂东县| 邵阳市| 温州市| 山西省| 南投市| 叙永县| 家居| 普格县| 沂源县| 龙井市| 札达县| 宜春市| 沧源| 南康市| 麻阳| 漳浦县| 合水县| 桓台县| 弥勒县| 西宁市| 玛多县|