Hi,
I think having to extend a base class is not a good idea. First of all
you deprive yourself of extending a class of a library you haven't
written (like something from Zend Framework or PEAR). Second it puts a
huge constraint on the code of the users of your library, because any
class they write needs to extend your base class. A slightly better
solution would be to use an interface.
A solution like this forces you to have some kind of framework with
general interfaces/classes used in all of your libraries. To my opinion
a user shouldn't have to set up an elaborate framework in PHP to prevent
memory leaks.
I've heard some good comments, but no real good solutions. So I think I
should just write the destroy function. I hope it will find its way into
PHP or (even better) that someone can find a way to prevent these memory
leaks.
Best regards,
Arnold
Richard Quadling schreef:
> In user land, I have an abstract_object like this
> (http://rquadling.php1h.com/abstract_object.html).
>
> I've come from a Delphi environment so some of the code you see is
> based upon some of the ideas I see in the TObject class.
>
> There are some comments, but the basic idea is there.
>
> On 05/12/06, Arnold Daniels <[EMAIL PROTECTED]> wrote:
>>
>>
>> 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
>> >> get
>> >> destroyed. I can off course write a method to break the
>> >> cross-reference,
>> >> but that's kind of a pain in the butt, especially if the
>> >> cross-reference
>> >> 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
>> problems.
>> 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
>> >> on
>> >> 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
>> > function.
>> >
>> >
>> >> 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
>> >> consequences.
>> >>
>> >
>> >
>> >> 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
>> > you don't.
>> >
>> > 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
>> > slow.
>> >
>> >
>> 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.
>>
>> Best regards,
>> Arnold
>>
>>
>
>