今天有小夥伴說 exit 和 die 有一點差異。我說 die 不就是 exit 的別名嗎?爲了證實個人觀點,翻了翻 PHP 的源碼,在 zend_language_scanner.l
中,很容易就能發現這關鍵字是同一個 token:html
<ST_IN_SCRIPTING>"exit" { return T_EXIT; } <ST_IN_SCRIPTING>"die" { return T_EXIT; }
因此最終也是同一個 Opcode:ZEND_EXIT。因此這兩個關鍵字沒有任何差異,這其實也沒什麼好說的。前端
我順便提醒了小夥伴們一句:不要用 exit 輸出整數。緣由也很簡單,在 PHP 官網的文檔裏就能看到:shell
void exit ([ string
$status
] )編程void exit ( int
$status
)函數若是
status
是一個字符串,在退出以前該函數會打印status
。測試若是
status
是一個 integer,該值會做爲退出狀態碼,而且不會被打印輸出。 退出狀態碼應該在範圍0至254,不該使用被PHP保留的退出狀態碼255。 狀態碼0用於成功停止程序。ui
因此若是 status 是一個整數,會被當成狀態碼輸出,而不是打印,因此若是想返回給前端是不可能的。.net
那麼這個狀態碼有什麼用呢?code
你們都知道 shell 腳本執行能夠返回一個狀態碼,PHP 的腳本的執行返回的狀態碼是同樣的,能夠在環境變量中被捕捉到:
Scholer: ~ $ php -r 'exit(254);' Scholer: ~ $ echo $? 254
個人好奇心又被勾起來了:若是給的是不在 0 ~ 255 之間的狀態碼會怎麼樣呢?通過測試,發現若是是大於 255 的狀態碼,會返回 status 對 256 求於以後的結果。若是是小於 0 的,在 -1 ~ - 255 之間時返回的是 status 256 求和的結果,小於 -256 的則是絕對值和 256 求餘。總之都在 0 ~ 255 之間。
接着探究下去。
exit 的實如今 zend_vm_def.h 中:
ZEND_VM_HANDLER(79, ZEND_EXIT, CONST|TMP|VAR|UNUSED|CV, ANY) { #if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED) USE_OPLINE SAVE_OPLINE(); if (OP1_TYPE != IS_UNUSED) { zend_free_op free_op1; zval *ptr = GET_OP1_ZVAL_PTR(BP_VAR_R); if (Z_TYPE_P(ptr) == IS_LONG) { EG(exit_status) = Z_LVAL_P(ptr); } else { zend_print_variable(ptr); } FREE_OP1(); } #endif
從代碼中咱們能夠很明顯的看出來經過 Z_TYPE_P
來檢測狀態碼的類型,若是是 long 的話就賦值給全局變量 exit_status
(EG 這個宏就是用來便捷的訪問全局變量的),若是不是,就調用 zend_print_variable
打印出來。
Z_LVAL_P
的聲明在 zend_operators.h 中:
#define Z_LVAL_P(zval_p) Z_LVAL(*zval_p) ... #define Z_LVAL(zval) (zval).value.lval
再進一步就是你們都知道的 PHP 解釋器中的變量定義了(我這份源碼仍是 PHP 5.5 的版本,不是 PHP7),在 zend.h 中:
typedef union _zvalue_value { long lval; /* long value */ double dval; /* double value */ struct { char *val; int len; } str; HashTable *ht; /* hash table value */ zend_object_value obj; } zvalue_value; struct _zval_struct { /* Variable information */ zvalue_value value; /* value */ zend_uint refcount__gc; zend_uchar type; /* active type */ zend_uchar is_ref__gc; };
因此這裏 exit_status
的值到這裏仍是一個長整形。
那麼問題就來了,爲何最終輸出的是 0 ~ 255 之間的狀態碼呢?老實說這個問題我吃的也不是很透,這須要對 Linux 環境編程足夠熟悉才行,這裏只能簡單的說一下。
經過 strace 跟蹤一下執行:
$ strace php -r 'exit(258);' >& strace.log
在結果的最後兩行能夠很清楚的看到:
... exit_group(258) = ? +++ exited with 2 +++
exit_group 中仍是原始值,但最終會變成 2 。PHP 自己並無對這個值作特殊處理,可是 exit 或者 main 函數中的 return,只能使用 0 ~ 255 之間的值,其餘值都會被處理。能夠寫一個簡單的程序測試:
int main(int argc, char const *argv[]) { return 258; }
結果:
Scholer: ~ $ ./test Scholer: ~ $ echo $? 2