PHP原理之异常机制深切剖判

PHP的那几个机制的准则是怎么?
在PHP每二个可独自施行的op
array最终的ZEND_HANDLE_EXCEPTION是用来干什么啊?
让我们从一个标题聊起, 上周的时候, blue5tar提了一个难点:”对于上面的代码,
onError明明施行了, 可是onException却尚无施行, 为何?”.

PHP的要命机制的法则是哪些?

深深精晓PHP之require/include顺序
//www.jb51.net/article/25867.htm
普及
在php手册中:

复制代码 代码如下:

在PHP每三个可单独实践的op
array最后的ZEND_HANDLE_EXCEPTION是用来干什么啊?

require() is identical to include() except upon failure it will also
produce a fatal E_ERROR level error. In other words, it will halt the
script whereas include() only emits a warning (E_WARNING) which
allows the script to continue.

<?php
function onError($errCode, $errMesg, $errFile, $errLine) {
echo “Error Occurred\n”;
throw new Exception($errMesg);
}
function onException($e) {
echo $e->getMessage();
}
set_error_handler(“onError”);
set_exception_handler(“onException”);
/* 小编未曾会以自家的名字命名文件, 所以这一个文件海市蜃楼 */
require(“laruence.php”);

让大家从三个主题材料谈到, 下一周的时候, blue5tar提了二个标题:”对于上面的代码,
onError明明实践了, 但是onException却未有实行, 为何?”.

实属在退步的时候,require是会中断php运维的,而include是足以继续运转的。
倒底有哪些的差别吧?大家带着这一个难题来共同进入PHP的主旨代码。
下边是二个PHP运维进度的图(这些图是来源于哪里的?鸟哥画的?)
金沙js333娱乐场 1

运营结果:

复制代码 代码如下:

补习一下:lex是代码扫描器,扫描代码用的,yacc是Yet Another Compiler
Compiler,效用是把任何一种代码的语法转成yacc语法,yacc正是解析器(真TMD绕)。
lex在c下的后缀是*.l yacc是*.y

复制代码 代码如下:

<?php
function onError($errCode, $errMesg, $errFile, $errLine) {
echo “Error Occurred\n”;
throw new Exception($errMesg);
}

正题
上边看操作记录:

Error Occurred
PHP Fatal error: main(): Failed opening required ‘laruence.php

function onException($e) {
echo $e->getMessage();
}

cc@cc-laptop:/opt/workspace$ svn checkout

php-src-5.3
从svn取最新的php源代码。

先是, 大家要知道, Require在含有贰个找不到的难点的时候,
会前后抛出俩个谬误,

set_error_handler(“onError”);

千帆竞发深入:

复制代码 代码如下:

set_exception_handler(“onException”);

cc@cc-laptop:/opt/workspace/php-src-5.3$ find . -type f -name “*.l”
-exec grep -Hn “require_once” {} \;
./Zend/zend_language_scanner.l:1093:”require_once” {
找出lex代码扫描器文件中冒出require_once的地方,zend_language_scanner.l的1093行。
1093 “require_once” {
1094 return T_REQUIRE_ONCE;
1095 }

WAENVISIONNING : 在PHP试图张开那一个文件的时候抛出.
E_COMPILE_E库罗德ROMurano : 从PHP展开文件的函数再次回到退步以往抛出

/* 小编并未会以自家的名字命名文件, 所以这个文件荒诞不经 */
require(“laruence.php”);

接下来再搜一下T_REQUIRE_ONCE,

而作者辈知道, set_error_handler是无法捕获E_COMPILE_ERROR错误的:
The following error types cannot be handled with a user defined
function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING,
E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in
the file where set_error_handler() is called.
故此, 在onError中, 只好捕获到第贰个WA奥迪Q5NING错误, 而在onError中抛出的要命,
为何未有被私下认可exception_handler捕获呢?
那将要说说PHP的不得了机制了.
了然opcode(深刻领悟PHP原理之Opcodes的校友都了解, 在PHP5.3从前,
每二个可独立运作的op array(文件, 函数,
方法)的末梢一条opcode都以ZEND_HANDLE_EXCEPTION,
而那些opcode是做什么用的呢?
原先在PHP中, 当有非常被throw的时候, 会跳到种种op array的末梢一行,
来推行那条ZEND_HANDLE_EXCEPTION, 伪码如下:

运维结果:

cc@cc-laptop:/opt/workspace/php-src-5.3$ find . -type f -name “*.y”
-exec grep -Hn “T_INCLUDE” {} \;
./Zend/zend_language_parser.y:52:%left T_INCLUDE T_INCLUDE_ONCE
T_EVAL T_REQUIRE T_REQUIRE_ONCE
./Zend/zend_language_parser.y:985: | T_INCLUDE expr {
zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); }
./Zend/zend_language_parser.y:986: | T_INCLUDE_ONCE expr {
zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC);
}

复制代码 代码如下:

复制代码 代码如下:

在985行相近,有如此一堆代码:

void on_throw_exception(zval *exception TSRMLS_DC) {

Error Occurred
PHP Fatal error: main(): Failed opening required ‘laruence.php

internal_functions_in_yacc:
T_ISSET ‘(‘ isset_variables ‘)’ { $$ = $3; }
| T_EMPTY ‘(‘ variable ‘)’ {
zend_do_isset_or_isempty(ZEND_ISEMPTY, &$$, &$3 TSRMLS_CC); }
| T_INCLUDE expr { zend_do_include_or_eval(ZEND_INCLUDE, &$$,
&$2 TSRMLS_CC); }
| T_INCLUDE_ONCE expr {
zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC);
}
| T_EVAL ‘(‘ expr ‘)’ { zend_do_include_or_eval(ZEND_EVAL, &$$,
&$3 TSRMLS_CC); }
| T_REQUIRE expr { zend_do_include_or_eval(ZEND_REQUIRE, &$$,
&$2 TSRMLS_CC); }
| T_REQUIRE_ONCE expr {
zend_do_include_or_eval(ZEND_REQUIRE_ONCE, &$$, &$2 TSRMLS_CC);
}
;

  1. 认清是不是业已有那三个抛出
  2. 记录exception
  3. 笔录下一条要试行的op line的序号
  4. 金沙js333娱乐场,下一条要进行的op line序号 = 当前op array的最终一条
    }

先是, 我们要驾驭, Require在包罗一个找不到的标题标时候,
会前后抛出俩个谬误,

于是乎,大家要求继续深刻查找zend_do_include_or_eval,

发表评论

电子邮件地址不会被公开。 必填项已用*标注