<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ### 7.7.4 引用計數 在擴展中操作與PHP用戶空間相關的變量時需要考慮是否需要對其引用計數進行加減,比如下面這個例子: ```php function test($arr){ return $arr; } $a = array(1,2); $b = test($a); ``` 如果把函數test()用內部函數實現,這個函數接受了一個PHP用戶空間傳入的數組參數,然后又返回并賦值給了PHP用戶空間的另外一個變量,這個時候就需要增加傳入數組的refcount,因為這個數組由PHP用戶空間分配,函數調用前refcount=1,傳到內部函數時相當于賦值給了函數的參數,因此refcount增加了1變為2,這次增加在函數執行完釋放參數時會減掉,等返回并賦值給$b后此時共有兩個變量指向這個數組,所以內部函數需要增加refcount,增加的引用是給返回值的。test()翻譯成內部函數: ```c PHP_FUNCTION(test) { zval *arr; if(zend_parse_parameters(ZEND_NUM_ARGS(), "a", &arr) == FAILURE){ RETURN_FALSE; } //如果注釋掉下面這句將導致core dumped Z_TRY_ADDREF_P(arr); RETURN_ARR(Z_ARR_P(arr)); } ``` 那么在哪些情況下需要考慮設置引用計數呢?一個關鍵條件是:操作的是與PHP用戶空間相關的變量,包括對用戶空間變量的修改、賦值,要明確的一點是引用計數是用來解決多個變量指向同一個value問題的,所以在PHP中來回傳遞zval的時候就需要考慮下是不是要修改引用計數,下面總結下PHP中常見的會對引用計數進行操作的情況: * __(1)變量賦值:__ 變量賦值是最常見的情況,一個用到引用計數的變量類型在初始賦值時其refcount=1,如果后面把此變量又賦值給了其他變量那么就會相應的增加其引用計數 * __(2)數組操作:__ 如果把一個變量插入數組中那么就需要增加這個變量的引用計數,如果要刪除一個數組元素則要相應的減少其引用 * __(3)函數調用:__ 傳參實際可以當做普通的變量賦值,將調用空間的變量賦值給被調函數空間的變量,函數返回時會銷毀函數空間的變量,這時又會減掉傳參的引用,這兩個過程由內核完成,不需要擴展自己處理 * __(4)成員屬性:__ 當把一個變量賦值給對象的成員屬性時需要增加引用計數 PHP中定義了以下宏用于引用計數的操作: ```c //獲取引用數:pz類型為zval* #define Z_REFCOUNT_P(pz) zval_refcount_p(pz) //設置引用數 #define Z_SET_REFCOUNT_P(pz, rc) zval_set_refcount_p(pz, rc) //增加引用 #define Z_ADDREF_P(pz) zval_addref_p(pz) //減少引用 #define Z_DELREF_P(pz) zval_delref_p(pz) #define Z_REFCOUNT(z) Z_REFCOUNT_P(&(z)) #define Z_SET_REFCOUNT(z, rc) Z_SET_REFCOUNT_P(&(z), rc) #define Z_ADDREF(z) Z_ADDREF_P(&(z)) #define Z_DELREF(z) Z_DELREF_P(&(z)) //只對使用了引用計數的變量類型增加引用,建議使用這個 #define Z_TRY_ADDREF_P(pz) do { \ if (Z_REFCOUNTED_P((pz))) { \ Z_ADDREF_P((pz)); \ } \ } while (0) #define Z_TRY_DELREF_P(pz) do { \ if (Z_REFCOUNTED_P((pz))) { \ Z_DELREF_P((pz)); \ } \ } while (0) #define Z_TRY_ADDREF(z) Z_TRY_ADDREF_P(&(z)) #define Z_TRY_DELREF(z) Z_TRY_DELREF_P(&(z)) ``` 這些宏操作類型都是zval或zval*,如果需要操作具體value的引用計數可以使用以下宏: ```c //直接獲取zend_value的引用,可以直接通過這個宏修改value的refcount #define GC_REFCOUNT(p) (p)->gc.refcount ``` 另外還有幾個常用的宏: ```c //判斷zval是否用到引用計數機制 #define Z_REFCOUNTED(zval) ((Z_TYPE_FLAGS(zval) & IS_TYPE_REFCOUNTED) != 0) #define Z_REFCOUNTED_P(zval_p) Z_REFCOUNTED(*(zval_p)) //根據zval獲取value的zend_refcounted頭部 #define Z_COUNTED(zval) (zval).value.counted #define Z_COUNTED_P(zval_p) Z_COUNTED(*(zval_p)) ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看