婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > PHP賦值的內部是如何跑的詳解

PHP賦值的內部是如何跑的詳解

熱門標簽:兼職做地圖標注好賺錢嗎 400 電話 辦理 亳州企業外呼系統 蘇州外呼系統有效果嗎 地圖標注怎么做商戶驗證 海南外呼系統方案 山東電銷卡外呼系統原理是什么 智能電銷語音機器人資訊 打開百度地圖標注

前言

在PHP中,一個變量被賦值,內部到底經歷了怎樣的邏輯判斷呢?

PHP在內核中是通過zval這個結構體來存儲變量的,它的定義在Zend/zend.h文件里

struct _zval_struct {zvalue_value value; /* 變量的值 */zend_uint refcount__gc;zend_uchar type; /* 變量當前的數據類型 */zend_uchar is_ref__gc;};typedef struct _zval_struct zval;//在Zend/zend_types.h里定義的:typedef unsigned int zend_uint;typedef unsigned char zend_uchar;

使用xdebug的xdebug_debug_zval函數可以打印出變量的refcount,is_ref的值。

$a = 'Hello World';$b = $a;

以上內容在內核中怎么執行呢?

zval *helloval;MAKE_STD_ZVAL(helloval);ZVAL_STRING(helloval, "Hello World", 1);zend_hash_add(EG(active_symbol_table), "a", sizeof("a"),helloval, sizeof(zval*), NULL);ZVAL_ADDREF(helloval); //這句很特殊,我們顯式的增加了helloval結構體的refcountzend_hash_add(EG(active_symbol_table), "b", sizeof("b"),helloval, sizeof(zval*), NULL);

可以看出來,當變量賦值的時候,其實兩個變量指向的是同一個地址空間。那么問題來了,如果指向同一個地址空間,那不是修改a,b也會跟著改變。這就涉及php的 寫時復制機制 。 以上代碼,如果后面一行為 $b = '123' 判斷過程如下:

  • 如果這個變量的zval部分的refcount小于2,代表沒有別的變量在用,則直接修改這個值
  • 否則,復制一份zval 的值,減少原zval的refcount的值,初始化新的zval的refcount,修改新復制的zval

簡單變量

先引用賦值后普通賦值

var_dump(memory_get_usage());$a = '1234567890';xdebug_debug_zval('a');var_dump(memory_get_usage());$b = $a;xdebug_debug_zval('a','b');var_dump(memory_get_usage());$c = $a;xdebug_debug_zval('a','b','c');var_dump(memory_get_usage());$a = '1234567890';var_dump(memory_get_usage());$b = $a;var_dump(memory_get_usage());$c = $a;

輸出內容如下:

int(121672)
a: (refcount=1, is_ref=0)='1234567890'

int(121776)
a: (refcount=2, is_ref=1)='1234567890'
b: (refcount=2, is_ref=1)='1234567890'

int(121824)
a: (refcount=2, is_ref=1)='1234567890'
b: (refcount=2, is_ref=1)='1234567890'
c: (refcount=1, is_ref=0)='1234567890'

int(121928)

$a 賦值,開辟了104byte空間,變量a refcount=1,is_ref=0

$b 賦值,開辟了48byte空間,變量a refcount=2,is_ref=1。48byte是符號表占用,a,b執行同一個地址空間

$c 賦值,開辟了104byte空間。由于a,b是引用,所以在c賦值的時候,會開辟新空間,復制a zval內容,并初始化refcount,is_ref,所以a 的refcount不變,c 的refcount=1

先普通賦值后引用賦值

var_dump(memory_get_usage());$a = '1234567890';xdebug_debug_zval('a');var_dump(memory_get_usage());$b = $a;xdebug_debug_zval('a','b');var_dump(memory_get_usage());$c = $a;xdebug_debug_zval('a','b','c');var_dump(memory_get_usage());

輸出內容如下:

int(121672)

a: (refcount=1, is_ref=0)='1234567890'
int(121776)

a: (refcount=2, is_ref=0)='1234567890'
b: (refcount=2, is_ref=0)='1234567890'
int(121824)

a: (refcount=2, is_ref=1)='1234567890'
b: (refcount=1, is_ref=0)='1234567890'
c: (refcount=2, is_ref=1)='1234567890'
int(121928)

$a 賦值,開辟了104byte空間,變量a refcount=1,is_ref=0

$b 賦值,開辟了48byte空間,變量a refcount=2,is_ref=1。48byte是符號表占用,a,b指向同一個地址空間

$c 賦值,開辟了104byte空間。由于a,c是引用,需要與b隔離開來,因此會賦值原有的zval,初始化zval,將a,c指向新復制的zval,同時原有的zval refcount-1

數組

$arr = [0=>'one'];
xdebug_debug_zval('arr');
$arr[1] = $arr;

xdebug_debug_zval('arr');

$arr[2] = $arr;
xdebug_debug_zval('arr');
unset($arr[1]);
xdebug_debug_zval('arr');
unset($arr[2]);
xdebug_debug_zval('arr');

輸出內容如下:

arr: (refcount=1, is_ref=0)=array ( 0 => (refcount=1, is_ref=0)='one')
)
arr: (refcount=1, is_ref=0)=array (
0 => (refcount=2, is_ref=0)='one',
1 => (refcount=1, is_ref=0)=array (
0 => (refcount=2, is_ref=0)='one'
)
)
arr: (refcount=1, is_ref=0)=array (
0 => (refcount=3, is_ref=0)='one',
1 => (refcount=2, is_ref=0)=array (
0 => (refcount=3, is_ref=0)='one'),
2 => (refcount=1, is_ref=0)=array (
0 => (refcount=3, is_ref=0)='one',
1 => (refcount=2, is_ref=0)=array (...)
)
)
arr: (refcount=1, is_ref=0)=array (
0 => (refcount=3, is_ref=0)='one',
2 => (refcount=1, is_ref=0)=array (
0 => (refcount=3, is_ref=0)='one',
1 => (refcount=1, is_ref=0)=array (...)
)
)
arr: (refcount=1, is_ref=0)=array (
0 => (refcount=1, is_ref=0)='one'
)
$arr = [0=>'one'];xdebug_debug_zval('arr');$arr[1] = $arr;xdebug_debug_zval('arr');$arr[2] = $arr;xdebug_debug_zval('arr');unset($arr[1]);xdebug_debug_zval('arr');unset($arr[2]);xdebug_debug_zval('arr');

輸出內容如下:

arr: (refcount=1, is_ref=0)=array (
0 => (refcount=1, is_ref=0)='one'
)
arr: (refcount=2, is_ref=1)=array (
0 => (refcount=1, is_ref=0)='one',
1 => (refcount=2, is_ref=1)=...
)
arr: (refcount=3, is_ref=1)=array (
0 => (refcount=2, is_ref=0)='one',
1 => (refcount=3, is_ref=1)=...,
2 => (refcount=2, is_ref=0)=array (
0 => (refcount=2, is_ref=0)='one',
1 => (refcount=3, is_ref=1)=...,
2 => (refcount=2, is_ref=0)=...)
)
arr: (refcount=2, is_ref=1)=array (
0 => (refcount=2, is_ref=0)='one',
2 => (refcount=2, is_ref=0)=array (
0 => (refcount=2, is_ref=0)='one',
1 => (refcount=2, is_ref=1)=...,
2 => (refcount=2, is_ref=0)=...)
)
arr: (refcount=2, is_ref=1)=array (
0 => (refcount=2, is_ref=0)='one'
)

上面段測試代碼很相似,差別只在arr[1]是否是引用賦值。

arr[1]非引用賦值的情況,arr[0]的refcount = 賦值次數+1,執行兩次unset之后,arr,arr[0]的refcount都跟開始定義的時候一致。 arr[1]引用賦值的情況,arr[0]的refcount = 非引用賦值次數+1,執行兩次unset之后,arr,arr[0] 的refcount都無法回到定義的時候的值。

主要原因在于arr[1]引用賦值,構成一個遞歸操作。 但是如果,至于這個refcount,真的說不明白。當沒有arr[2]賦值的時候,執行unset, arr refcount能回到1 。從下面這張圖更加清晰看出內部遞歸引用


當出現上面這種情況,refcount本該=1,但實際上面沒有被設置為1,這種情況就會出現內存泄漏。上面代碼循環執行100次,內存從一開始121096 上升到169224,內存占用上升了5k 。

對象

$user = new User();
 $m = $user;
 $user->user ='';
 $user->name = 'sdfsdfs';
 xdebug_debug_zval('user','m');

以上內容輸出

(refcount=2, is_ref=0)=class User {
public $name = (refcount=1, is_ref=0)='sdfsdfs';
public $model = (refcount=1, is_ref=0)=NULL;
public $user = (refcount=1, is_ref=0)=''
}
m: (refcount=2, is_ref=0)=class User {
public $name = (refcount=1, is_ref=0)='sdfsdfs';
public $model = (refcount=1, is_ref=0)=NULL;
public $user = (refcount=1, is_ref=0)=''
}

xdebug給出的is_ref=0。refcount與普通變量一直。但是類的賦值是引用賦值。

$user = new User();
 $user->user = $user;
 $user->name = 'sdfsdfs';
 xdebug_debug_zval('user');
 unset($user);

上面內容輸出:

user: (refcount=2, is_ref=0)=class User { public $name = (refcount=1, is_ref=0)='sdfsdfs'; public $user = (refcount=2, is_ref=0)=... }

這里由于類的賦值是引用賦值,索引也構成了一個遞歸操作,這樣也會跟數組一樣出現內存泄漏的情況。對以下代碼個自行100次

$user = new User();
 $user->user = $user;
 $user->name = 'sdfsdfs';
 xdebug_debug_zval('user');
 unset($user);
$user = new User();
 $user->user = new Order();
 $user->name = 'sdfsdfs';
 xdebug_debug_zval('user');
 unset($user);

第一段代碼前后內存差1408 byte. 第二段代碼差208 byte。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

您可能感興趣的文章:
  • php 傳值賦值與引用賦值的區別
  • PHP讀取txt文件的內容并賦值給數組的代碼
  • 詳解PHP數組賦值方法
  • php foreach 使用(與運算符)引用賦值要注意的問題
  • php中給js數組賦值方法
  • PHP5 的對象賦值機制介紹
  • PHP變量賦值、代入給JavaScript中的變量
  • php數組操作之鍵名比較與差集、交集賦值的方法
  • PHP基礎陷阱題(變量賦值)

標簽:綏化 呼倫貝爾 萊蕪 金華 安康 紹興 清遠 溫州

巨人網絡通訊聲明:本文標題《PHP賦值的內部是如何跑的詳解》,本文關鍵詞  PHP,賦值,的,內部,是,如何,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《PHP賦值的內部是如何跑的詳解》相關的同類信息!
  • 本頁收集關于PHP賦值的內部是如何跑的詳解的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    国产无一区二区| 国产精品美日韩| 精品人在线二区三区| 日韩精品电影在线| 91丨porny丨中文| 久久夜色精品一区| 三级成人在线视频| 欧亚一区二区三区| 亚洲美女视频一区| 成人免费看片app下载| 久久久久久久综合狠狠综合| 免费高清在线一区| 欧美一区二区三区免费在线看| 日韩国产在线观看一区| 久久先锋影音av鲁色资源网| gogo大胆日本视频一区| 亚洲成a天堂v人片| 久久蜜臀中文字幕| 欧美日韩一区成人| 精品在线一区二区| 亚洲欧美日韩久久精品| 91麻豆精品国产91久久久使用方法| 久热成人在线视频| 欧美色中文字幕| 日韩亚洲欧美一区| 91女厕偷拍女厕偷拍高清| 日韩精品福利网| 综合网在线视频| 日韩写真欧美这视频| 99精品国产热久久91蜜凸| 天天操天天干天天综合网| 国产精品午夜电影| 国产成人免费在线视频| 欧美狂野另类xxxxoooo| 麻豆国产欧美日韩综合精品二区| 欧美一级免费观看| a亚洲天堂av| 精品影视av免费| 亚洲精品中文字幕乱码三区| 精品成人私密视频| 91黄色免费版| 国产99久久久国产精品潘金网站| 视频一区中文字幕| 亚洲尤物视频在线| 亚洲欧美成aⅴ人在线观看| 久久久精品tv| 久久久国产精品麻豆| 欧美成人a视频| 欧美一区二区精品在线| 91精品1区2区| 黄色日韩网站视频| 综合色中文字幕| 日韩一级片网址| 色94色欧美sute亚洲13| 国产成人免费网站| 狠狠色2019综合网| 日本伊人午夜精品| 亚洲国产欧美另类丝袜| 国产精品福利影院| 欧美国产日产图区| 国产亚洲欧洲997久久综合| 欧美大片日本大片免费观看| 5月丁香婷婷综合| 欧美电影在线免费观看| 色婷婷久久久综合中文字幕| 99精品久久免费看蜜臀剧情介绍| 播五月开心婷婷综合| 成人免费毛片嘿嘿连载视频| 成人午夜激情片| eeuss影院一区二区三区| av一区二区三区| 97超碰欧美中文字幕| 不卡视频在线看| 在线亚洲一区观看| 欧美一区二区私人影院日本| 日韩欧美自拍偷拍| 国产日产精品1区| 亚洲日穴在线视频| 亚洲综合色噜噜狠狠| 日韩电影在线一区| 国产一区二区看久久| 国产精品性做久久久久久| 成人免费视频国产在线观看| 色婷婷激情久久| 91麻豆精品国产91久久久使用方法 | 欧美午夜片在线看| 欧美电影在哪看比较好| 精品入口麻豆88视频| 欧美国产日韩a欧美在线观看 | 亚洲成a人片在线不卡一二三区| 国产精品一级二级三级| 国模无码大尺度一区二区三区| 美女免费视频一区二区| 激情欧美一区二区三区在线观看| 国产99久久久国产精品免费看 | 丁香婷婷综合激情五月色| 99久久综合狠狠综合久久| 欧美日韩国产精选| 久久亚洲一区二区三区明星换脸| 国产精品妹子av| 日韩在线播放一区二区| 国产呦萝稀缺另类资源| 欧洲人成人精品| 久久综合九色综合欧美就去吻| 欧美日韩一区二区三区在线看| 国产成人精品影视| 欧美中文一区二区三区| 日韩精品中文字幕一区二区三区| 亚洲国产精品激情在线观看| 性做久久久久久免费观看| 国产91在线|亚洲| 欧美人与z0zoxxxx视频| 中文字幕在线不卡视频| 久久er99热精品一区二区| aaa亚洲精品| 2017欧美狠狠色| 麻豆一区二区在线| 色噜噜偷拍精品综合在线| 国产亚洲1区2区3区| 青娱乐精品在线视频| 在线观看日韩毛片| 国产精品二三区| 中文欧美字幕免费| 欧美aaaaaa午夜精品| av网站免费线看精品| 欧美日韩在线观看一区二区 | 国产精品欧美经典| 韩国毛片一区二区三区| 91.麻豆视频| 一区二区三区在线视频观看| 国产成人高清视频| 精品盗摄一区二区三区| 日韩黄色在线观看| 欧美日韩和欧美的一区二区| 亚洲一区在线观看网站| 成人精品视频一区| 国产精品国产成人国产三级| 久久亚洲影视婷婷| 久久综合丝袜日本网| 亚洲国产美国国产综合一区二区| 成人性生交大片免费看在线播放 | 成人av第一页| 国产精品免费av| 99在线视频精品| 亚洲蜜臀av乱码久久精品| 91一区一区三区| 亚洲男人天堂av| 69久久99精品久久久久婷婷 | 亚洲欧美另类久久久精品 | 91精品国产综合久久福利 | 玉米视频成人免费看| 国产精品一区二区视频| 337p日本欧洲亚洲大胆精品| 国产精选一区二区三区| 欧美国产视频在线| 99国内精品久久| 亚洲成年人影院| 欧美精品一区二区不卡| 成人免费视频网站在线观看| 亚洲欧洲国产日韩| 欧美日韩精品欧美日韩精品 | 中文字幕第一页久久| 久久中文娱乐网| 国产成人在线色| 国产精品久久三区| 亚洲日本va午夜在线电影| 一本色道久久综合亚洲aⅴ蜜桃| 玉足女爽爽91| 久久影音资源网| 99国产精品久久久久久久久久| 亚洲一区二区三区四区五区中文| 日韩一区二区在线看| 成人精品电影在线观看| 天天操天天干天天综合网| 日本一区二区三级电影在线观看 | 日韩视频在线观看一区二区| gogo大胆日本视频一区| 捆绑调教一区二区三区| 亚洲精选视频免费看| 欧美va日韩va| 欧美日韩精品系列| 99re亚洲国产精品| 狠狠色2019综合网| 亚洲国产一区二区在线播放| 久久久精品免费免费| 91 com成人网| 在线视频亚洲一区| 成人av网址在线| 久久99精品国产麻豆婷婷洗澡| 夜夜爽夜夜爽精品视频| 国产午夜精品理论片a级大结局| 欧美日韩三级视频| av亚洲精华国产精华| 国产自产v一区二区三区c| 香蕉av福利精品导航| 最近日韩中文字幕| 日本一区二区在线不卡| 精品福利一二区| 日韩限制级电影在线观看| 欧美在线制服丝袜|