Hi Rowan,

> Do you know how the equivalent code works with function-scoped variables?
> As far as I can see, returning from a function will successfully call multiple
> destructors even if one of them throws an exception. Could exiting block
> scope use that same algorithm?

PHP literally frees all of the variables (even the ones which are definitely 
not reference counted)
without stopping if any of them throw an exception until everything is freed.
`i_free_compiled_variables` is called when exiting the function scope (e.g. 
throw/return).
(the caller also decreases reference counts to the closure/$this, extra 
unexpected arguments, etc)

```
static zend_always_inline void i_free_compiled_variables(zend_execute_data 
*execute_data) /* {{{ */
{
        zval *cv = EX_VAR_NUM(0);
        int count = EX(func)->op_array.last_var;
        while (EXPECTED(count != 0)) {
                i_zval_ptr_dtor(cv);
                cv++;
                count--;
        }
}
```

> Having the variable become inaccessible but not actually deallocated
> seems like it would cause a lot of confusion.

Good point about resources, I forgot about freeing being automatic.

I'm starting to lean towards deallocating.

If this was used within a try block or a top-level statement,
this could probably add a new opcode to free a variable that could throw
without checking for the exception,
and only the last opcode would need to throw the last exception.
(adding a new opcode to ensure deallocation of all variables without the 
equivalent of
a `try/finally` block for every additional `let` variable)

For global variables, there's already the problem in the engine that 
`__destruct()`
could itself create global variables of the same/different name.

- Tyson
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to