Note that there are some explanatory texts on larger screens.

plurals
  1. POdestructing an object with references to itself
    text
    copied!<p>While debugging a piece of code that was exhausting the memory, I found a very interesting problem, and most importantly I don't know how to fix it.</p> <p>The application consists roughly of a single <code>Survey</code> object, which contains a number of <code>Question</code> objects. The Question objects contain a reference to the Survey they're in, this is needed to be able to fetch answers from other Questions for instance.</p> <hr> <p>The following loop was causing the memory overflow:</p> <pre><code>foreach ( $survey_ids_arr as $survey_id ) { $Survey = new Survey( $survey_id ); } </code></pre> <p>Nothing really exotic is happening in the Survey constructor; </p> <ul> <li>fetching its properties from the database</li> <li>fetching all questions' properties from the database</li> <li>creating a Question object for each question (passing a reference to $this)</li> <li>adding all Question objects to an internal array</li> </ul> <p>and from looking at the code, you would say that in each iteration the object is cleared from memory because the $Survey variable is overwritten. Right?? Wrong :)</p> <p>The memory is piling up as the script goes through the loop - adding <code>memory_get_usage()</code> calls shows that the memory used by the Survey object isn't freed as expected, at the moment another object is assigned to the <code>$Survey</code> variable. Even calling <code>unset( $Survey )</code> at the end of the loop does not free the memory.</p> <hr> <p>The culprit are the references to <code>$this</code> that are passed to the Question objects upon creation. These references prevent the object to be cleared from memory - as the manual on php.net states: </p> <blockquote> <p>The destructor method will be called as soon as all references to a particular object are removed</p> </blockquote> <p>So what prevents the object from being cleaned up, is the references it has in it to itself. Nice, huh? :)</p> <p>So, the problem is my object is a memory killer. Unfortunately, I can't think of a solution (other than writing an ugly method which clears the questions and calling that from the loop). The destructor in Survey is not an option; as stated above this is not called <em>because</em> the Question objects still have references.</p> <p>Any ideas? Someone must have run into this problem already - the parent-containing-child-objects is not an uncommon architecture, is it?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload