What is the principle of PHP's exception mechanism?
What is the ZEND_HANDLE_EXCEPTION at the end of each independently executable op array in PHP used for?
Let's start with a question, last week When, blue5tar asked a question: "For the following code, onError is obviously executed, but onException is not executed, why?".
Copy code The code is as follows:
function onError($errCode, $errMesg, $errFile, $errLine) {
echo "Error Occurredn";
throw new Exception($errMesg);
}
function onException($e) {
echo $e->getMessage();
}
set_error_handler( "onError");
set_exception_handler("onException");
/* I never name a file after me, so this file doesn't exist*/
require(" laruence.php");
Run result:
Copy code The code is as follows:
Error Occurred
PHP Fatal error: main(): Failed opening required 'laruence.php
First of all, we need to know that when Require contains a problem that cannot be found, it will be thrown forward and backward Two errors occurred,
Copy code The code is as follows:
1. WARNING: thrown when PHP tries to open this file Out.
2. E_COMPILE_ERROR: Throws after failure returns from the PHP file opening function
And we know that set_error_handler cannot capture the E_COMPILE_ERROR 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.
So, in onError, only The first WARNING error can be caught, but why is the exception thrown in onError not caught by the default exception_handler?
This is about PHP’s exception mechanism.
Understand opcode (Students who have a deep understanding of PHP principles and Opcodes all know that before PHP5.3, the last opcode of every op array (file, function, method) that can be run independently is ZEND_HANDLE_EXCEPTION, and what is this opcode used for? What?
It turns out that in PHP, when an exception is thrown, it will jump to the last line of each op array to execute this ZEND_HANDLE_EXCEPTION. The pseudo code is as follows:
Copy code The code is as follows:
void on_throw_exception(zval *exception TSRMLS_DC) {
1. Determine whether an exception has been thrown
2. Record exception
3. Record the serial number of the next op line to be executed
4. The serial number of the next op line to be executed = the last one of the current op array
}
Well, just like rewriting the ip register, rewriting the sequence number of the next op line to be executed changes the flow of the program. In this way, it will enter the processing logic of ZEND_HANDLE_EXCEPTION.
And in ZEND_HANDLE_EXCEPTION, It will determine whether this exception is in try catch,
Copy the code The code is as follows:
If so, put the following An op line to be executed is set as the first catch op line and continues execution.
If not, destroy some unnecessary variables and opline, and then directly end the execution process
Some students may ask: "When will the default exception handling function (user_exception_handler) set by set_exception_handler take effect?"
Well, it is determined whether there is default exception handling after the execution is completed and the LOOP is exited. Function, only call it if available:
Copy code The code is as follows:
//Execute
zend_execute( EG(active_op_array) TSRMLS_CC);
if (EG(exception)) {
if (EG(user_exception_handler)) {
Call the user-defined default exception handler function
} else {
Not Caught exception
}
} else {
No exception
}
destroy_op_array(EG(active_op_array) TSRMLS_CC);
efree(EG(active_op_array));
PHP exception process
When PHP encounters a Fatal Error, it will directly zend_bailout, and zend_bailout will cause the program flow to directly skip the above code segment, which can also be understood as direct exit ( longjmp), which results in user_exception_handler not having a chance to work.
After understanding this, I think the reason for the problem at the beginning of the article is very clear, right?
Finally, regarding ZEND_HANDLE_EXCEPTION, Some students may have questions: If this is the case, then why does every independently executable op array end up with this ZEND_HANDLE_EXCEPTION? The simplest, if there is no throw in a function, then this opcode is obviously unnecessary? Hehe, you are very smart. Starting from PHP 5.3, it has been adjusted according to your ideas. Only at the throw moment, the ZEND_HANDLE_EXCEPTION opline will be dynamically generated.
PHP5 changelog:
Changed exception handling . Now each op_array doesn't contain ZEND_HANDLE_EXCEPTION opcode in the end. (Dmitry)
http://www.bkjia.com/PHPjc/322299.htmlwww.bkjia.comtruehttp: //www.bkjia.com/PHPjc/322299.htmlTechArticleWhat is the principle of PHP’s exception mechanism? The ZEND_HANDLE_EXCEPTION at the end of each independently executable op array in PHP is used What are you here for? Let’s start with a question. Last week,...