On 04/02/13 10:57, Ángel González wrote:
<snip>
The memory will stop growing (on my machine) at ~2491584 bytes and the
loop is able to run forever,
creating each eval() furthermore uniqe ano-function's but not
endless-filling Zend-internal tables.
but this still leaves the function record itself in the
function_table hash so with a non-zero reference count and this
doesn't get DTORed until request shutdown
Not familar with the Zend-internals but just about so i was imaging
and expecting it.
That why i [still] also confused/wondering why in the 2nd example the
memory will not grow *endless*.
It seems that the function records in the function_table will be
DTORed (or similar cleaned up) before request-shutdown at some point...
Could this be the case?
As you are reassigning $ano_fnc, the old closure is being destructed.
Had you used create_function(), it wouldn't happen.
Now the question is, if it is correctly freeing the functions (and it is
good that it does so), why is it not doing it when they have different
lengths?
It's a bug. The Closure class DTOR does not delete the derefenced
function from the CG(function_table).
If you did the eval at line 20 in say /tmp/xx.php then the
INCLUDE_OR_EVAL instruction calls the Zend compiler with the args:
(1) the source to be compiled and
(2) the title "/tmp/x.php(20) : eval()'d code"
The compiler than gives the closure function a magic name:
"\0{closure}/tmp/x.php(20) : eval()'d code0xHHHHHHHH"
where 0xHHHHHHHH is the hex address of the "function" substring in the
evaluated string. The compiler uses a zend_hash_update to insert this
into the CG(function_table).
What happens if you use a fixed length string replacing another string
of the same length dropping its refcount to 0 is that the allocator is
clever and will tend to reallocate the old one and hence the address of
the string is the same and the address of the offset of the "function"
substring is the same so it regenerates the same magic name -- pretty
much as an accidental side-effect. When this happens, it's this hash
update function that calls the DTOR on any pre-existing function with
this name.
I simply put a breakpoint on the relevant line in the
zend_do_begin_function_declaration() code and if you used a fixed offset
into the same string you only got one {closure} entry. If the
allocation ended up "randomizing" the address, then the {closure}
entries grew until memory exhaustion.
As I said -- interesting. Need to think about the consequences before I
submit a bugrep.
Regards
Terry