Richard Lynch schreef:
On Mon, December 4, 2006 7:21 pm, Arnold Daniels wrote:
I'm struggling with the problem that cross-referenced objects don't
destroyed. I can off course write a method to break the
but that's kind of a pain in the butt, especially if the
is not strait forward.
Seems to me that a simple unset() on the data members in userland
coude so PHPs refcount is decremented ought to do it...
If a user creates a monstrous data structure and doesn't prune it, how
much responsibility can PHP take for that?
But maybe I'm just being naive.
I myself run into problems when implementing parent/child relationships
within object. I probably use PHP a bit different than the regular user
and therefor run into different problems, but with more elaborate
frameworks being build, I think more people will run into these kind of
Think about a DOM implementation fully in PHP (I'm not building that,
but just to give you an idea). Using uset() on each child wouldn't do
much good, since each also holds a parent/child relationship with its
children and therefor the child is not destroyed, meaning the parent is
not destroyed. To overcome this you need implement a method destroy(),
which runs through all property to see if it is a DOM object and call
the destroy() on it. But now imagine another class which has properties
with objects of all kinds of classes, some of which have parent/child
relationships. Now you need all these classes to implement some sort of
destroyable interface. I don't really like a solution like this. With
the destroy function you would still need to walk through the children
and call destroy forcing an unset in the destructor of the class, but
it's a step up.
To solve this I'm thinking of building one of 2 thing:
1.) Write a destroy() function which works much like a close function
a recourse, changing the object to a zval of type 'unknown'.
2.) Specify that a property of an object does not count for the
reference count of a zval.
I don't think this is a Good Idea...
Seems like it would be WAY too easy for userland code to end up with a
0 for the refcount and then GC kicks in.
Yes, that is what I want. If the parent object is unset, the parent
property of the child object should be set to unknown or something. But
I guess that the memory is freed and the zval isn't set to unknown and
you would just get unexpected results.
3.) Write code to find cross-references and destroy the objects still.
The first solution should be quite easy to implement, but you need to
call destroy() to free the object, introducing the whole alloc/free
responsibility thing to PHP.
Just use unset() for this, rather than introduce yet another confusing
The second solution would require some extra keyword within the class,
but require no special code within the code using the object. Though I
wouldn't have a clue how how to implement this or what would be the
I don't think the third solution is really possible or would at least
cause performance problems.
Finding a "dead branch" of cyclic structures is basic CS stuff.
Add a second temp "refcount" and start walking the graph.
Either you end up with something known to be in the GLOBAL scope, or
It can take a long time, depending on the size of the graph, but it's
just pointer-chasing and integer arithmetic, so shouldn't be THAT
I don't really see this solution. I wouldn't unnecessarily find anything
in the GLOBAL scope. When using unset or returning from a function, a
check should be made to find if the variable is used within the scope of
the call stack, global or statically. To my knowledge (which is small
on the PHP internals subject) it is only possible to see how many
references to the object there are, not where there references are.
Thank you for commenting on my e-mail. I hope you understand where I'm
coming from with this problem and understand why unset will not do. I
hope that you or perhaps someone else might have some other comments or
solutions I haven't yet thought of.