日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
解讀PHP異常機(jī)制的流程及原理

PHP的異常機(jī)制的原理是什么?在PHP每一個(gè)可獨(dú)立執(zhí)行的op array***的ZEND_HANDLE_EXCEPTION是用來干什么呢?讓我們從一個(gè)問題說起。

成都創(chuàng)新互聯(lián),專注為中小企業(yè)提供官網(wǎng)建設(shè)、營銷型網(wǎng)站制作、響應(yīng)式網(wǎng)站設(shè)計(jì)、展示型網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作等服務(wù),幫助中小企業(yè)通過網(wǎng)站體現(xiàn)價(jià)值、有效益。幫助企業(yè)快速建站、解決網(wǎng)站建設(shè)與網(wǎng)站營銷推廣問題。

對于一下代碼,onError明明執(zhí)行了, 但是onException卻沒有執(zhí)行, 為什么呢?

 
 
 
 
  1. function onError($errCode, $errMesg, $errFile, $errLine) {    
  2. echo "Error Occurred\n";    
  3. throw new Exception($errMesg);
  4. function onException($e) {    
  5. echo $e->getMessage();
  6. set_error_handler("onError"); 
  7. set_exception_handler("onException"); 
  8. /* 我從不會(huì)以我的名字命名文件, 所以這個(gè)文件不存在 */
  9. require("laruence.php");

運(yùn)行結(jié)果:

 
 
 
 
  1. Error Occurred
  2. PHP Fatal error: main(): Failed opening required 'laruence.php

首先, 我們要知道, Require在包含一個(gè)找不到的問題的時(shí)候, 會(huì)前后拋出倆個(gè)錯(cuò)誤:

1. WARNING : 在PHP試圖打開這個(gè)文件的時(shí)候拋出。

2. E_COMPILE_ERROR : 從PHP打開文件的函數(shù)返回失敗以后拋出。

而我們知道, set_error_handler是不能捕獲E_COMPILE_ERROR錯(cuò)誤的。所以, 在onError中, 只能捕獲到***個(gè)WARNING錯(cuò)誤, 而在onError中拋出的異常, 為什么沒有被默認(rèn)exception_handler捕獲呢?這就要說說PHP的異常機(jī)制了.

了解opcode的同學(xué)都知道, 在PHP5.3以前, 每一個(gè)可獨(dú)立運(yùn)行的op array(文件, 函數(shù), 方法)的***一條opcode都是ZEND_HANDLE_EXCEPTION, 而這個(gè)opcode是做什么用的呢?

原來在PHP中, 當(dāng)有異常被throw的時(shí)候, 會(huì)跳到每一個(gè)op array的***一行, 來執(zhí)行這條ZEND_HANDLE_EXCEPTION, 偽碼如下:

 
 
 
 
  1. void on_throw_exception(zval *exception TSRMLS_DC) {
  2. 1. 判斷是否已經(jīng)有異常拋出
  3. 2. 記錄exception
  4. 3. 記錄下一條要執(zhí)行的op line的序號
  5. 4. 下一條要執(zhí)行的op line序號 = 當(dāng)前op array的***一條
  6. }

就和改寫ip寄存器一樣, 改寫下一條要執(zhí)行的op line的序號, 就改變了程序的流向, 這樣, 就會(huì)進(jìn)入到了ZEND_HANDLE_EXCEPTION的處理邏輯中.而在ZEND_HANDLE_EXCEPTION中, 會(huì)判斷這個(gè)異常是否在try catch中。

◆如果是,則把下一條要執(zhí)行的op line, 置為***個(gè)catch的op line, 并繼續(xù)執(zhí)行。

◆如果不是,則銷毀一些不需要的變量, 和opline, 然后直接結(jié)束執(zhí)行過程。

這里有的同學(xué)要問了:”那set_exception_handler設(shè)置的異常默認(rèn)處理函數(shù)(user_exception_handler)什么時(shí)候起作用呢?” 是在執(zhí)行完成退出執(zhí)行LOOP以后才判斷是否有默認(rèn)異常處理函數(shù), 如果有才調(diào)用:

 
 
 
 
  1. //執(zhí)行
  2. zend_execute(EG(active_op_array) TSRMLS_CC);
  3. if (EG(exception)) {     
  4.    if (EG(user_exception_handler)) {          
  5.        調(diào)用用戶定義的默認(rèn)異常處理函數(shù)     
  6.     } 
  7.     else {          
  8.        未捕獲的異常     
  9.     }
  10. else {     
  11. 沒有異常
  12.       }
  13. destroy_op_array(EG(active_op_array) TSRMLS_CC);
  14. efree(EG(active_op_array));

PHP異常流程

注: 圖中有一處不嚴(yán)謹(jǐn), 即在確定是否***一個(gè)catch塊的時(shí)候, 會(huì)同時(shí)判斷(is_a), 如果是才進(jìn)入***一個(gè)catch塊執(zhí)行。

而PHP在遇到Fatal Error的時(shí)候, 會(huì)直接zend_bailout, 而zend_bailout會(huì)導(dǎo)致程序流程直接跳過上面代碼段, 也可以理解為直接exit了(longjmp), 這就導(dǎo)致了user_exception_handler沒有機(jī)會(huì)發(fā)生作用。了解到這些, 我想文章開頭的問題的為什么? 也就很清晰了吧?

***, 關(guān)于ZEND_HANDLE_EXCEPTION, 也許有同學(xué)會(huì)有疑問: 如果是這樣, 那為什么每一個(gè)可獨(dú)立執(zhí)行的op array***都有這個(gè)ZEND_HANDLE_EXCEPTION呢? 最簡單的, 如果一個(gè)函數(shù)中不會(huì)throw, 那么這個(gè)opcode是明顯不需要的? 你很聰明, PHP 5.3開始, 已經(jīng)按照你的想法調(diào)整了。只有在throw時(shí)刻, 才會(huì)動(dòng)態(tài)的生成ZEND_HANDLE_EXCEPTION opline.


網(wǎng)頁題目:解讀PHP異常機(jī)制的流程及原理
鏈接地址:http://m.5511xx.com/article/coipcde.html