Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:26813 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 39747 invoked by uid 1010); 6 Dec 2006 13:36:03 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 39732 invoked from network); 6 Dec 2006 13:36:03 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 6 Dec 2006 13:36:03 -0000 Authentication-Results: pb1.pair.com header.from=info@adaniels.nl; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=info@adaniels.nl; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain adaniels.nl from 82.94.235.198 cause and error) X-PHP-List-Original-Sender: info@adaniels.nl X-Host-Fingerprint: 82.94.235.198 hyak.bean-it.nl Received: from [82.94.235.198] ([82.94.235.198:42263] helo=hyak.bean-it.nl) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id EB/0F-54198-CF6C6754 for ; Wed, 06 Dec 2006 08:35:27 -0500 Received: from [127.0.0.1] (bean-it.xs4all.nl [213.84.27.165]) (authenticated bits=0) by hyak.bean-it.nl (8.13.4/8.13.4/Debian-3sarge3) with ESMTP id kB6DYZ8x009717; Wed, 6 Dec 2006 14:34:43 +0100 Message-ID: <4576C6E5.301@adaniels.nl> Date: Wed, 06 Dec 2006 14:34:29 +0100 User-Agent: Thunderbird 1.5.0.8 (Windows/20061025) MIME-Version: 1.0 To: RQuadling@GoogleMail.com CC: internals@lists.php.net References: <4574C97F.8020507@adaniels.nl> <22319.204.16.229.245.1165342794.squirrel@www.l-i-e.com> <4575F689.3000709@adaniels.nl> <10845a340612060040g7b04b612vf4a89873a2478473@mail.gmail.com> In-Reply-To: <10845a340612060040g7b04b612vf4a89873a2478473@mail.gmail.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Virus-Scanned: by amavisd-new X-Spam-Status: No, score=0.4 required=4.0 tests=BAYES_00,URIBL_BLACK autolearn=no version=3.1.3 X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on hyak.bean-it.nl Subject: Re: [PHP-DEV] destruction of cross-referenced objects From: info@adaniels.nl (Arnold Daniels) 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 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 >> >> > >