<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[[Erledigt] Speicherfreigabe im binärem Baum - Wie StackOverFlow vermeiden?]]></title><description><![CDATA[<p>Hallo ihr C++-Freunde,<br />
ich hab mal eine Frage an die Fachkundigen Leute hier.</p>
<p>Im Rahmen einer Semesterarbeit muss ich eine Datenstruktur erstellen, die Elemente sequenziell anordnet und dabei sowohl Speicher- als auch Laufzeit- effizient in Bezug auf die Konkatenation arbeitet. Der Name dieser Datenstruktur soll &quot;Sequence&quot; sein</p>
<p>Um das zu realisieren wurde intern mit einem Baum gearbeitet,<br />
der ähnlich einem binären Baum arbeitet.</p>
<p>Der Aufbau usw. ist alles in Ordnung und funktioniert soweit einwandfrei. Allerdings gibt es ein Problem im Destruktor bzw. bei der Speicherfreigabe.<br />
Der Baum besteht aus Elementen der Klasse &quot;SequenceNode&quot; die sich wiederum einen Referenzzähler merken um feststellen zu können ob es noch Verweise auf dieses Objekt gibt bzw. ob das Objekt gelöscht werden kann. Stirbt jetzt einer dieser Knoten muss er seinem rechten und linken Nachfolger natürlich mitteilen, dass es eine Referenz weniger gibt, die auf sie zeigt.</p>
<p>Wenn wir uns folgenden Code ansehen</p>
<pre><code class="language-cpp">{
Sequence&lt;unsigned&gt; s1; 

for(unsigned ui = 1; ui &lt;= 10000000; ++ui) 
    s1 = s1 + ui
std::cout &lt;&lt; &quot;ende&quot; &lt;&lt; std::endl;
}
</code></pre>
<p>Es wird eine Sequenz mit 10Mio Einträgen erstellt. Danach wird &quot;ende&quot; auf dem Bildschirm ausgegeben und am Ende des Blockes wird die Sequenz gelöscht.<br />
Es wird also der Destruktor von &quot;Sequence&quot; aufgerufen.</p>
<pre><code class="language-cpp">~Sequence()
{ 
    if(m_Root != 0) 
       m_Root-&gt;addRefCount(-1); 
}
</code></pre>
<p>Die Sequenz verwaltet einen Pointer auf ein Wurzelelement des internen Baums.<br />
Diesem Wurzelelement muss nun mitgeteilt werden, dass es eine Referenz weniger gibt.</p>
<p>Die Methode addRefCount befindet sich in der Klasse SequenceNode</p>
<pre><code class="language-cpp">void addRefCount(int value)
        {
            m_RefCount += value;
            if(m_RefCount &lt; 1)
                delete this;
        }
</code></pre>
<p>Sobald hier also der Referenzzähler &lt; 1 wird, wir das Objekt gelöscht und ruft den eigenen Destruktor auf.</p>
<pre><code class="language-cpp">~SequenceNode()
        {
            if(m_Left != 0)
                m_Left-&gt;addRefCount(-1);
            if(m_Right != 0)
                m_Right-&gt;addRefCount(-1);
        }
</code></pre>
<p>Dabei kommt es bei 10 Mio Elementen zu einer tiefen Rekursion,<br />
da jeder sterbende Knoten seinem rechten und linken Nachfolger mitteilen muss das es eine Referenz weniger gibt, und die ggf. dann ihren Nachfolgern usw.</p>
<p>Frage ist jetzt, wie man die Destruktoren so umschreiben kann,<br />
das es zu keinem StackOverflow mehr kommt, aber der Speicherplatz korrekt freigegeben wird.</p>
<p>Hat jemand eine Idee/ Tipp für mich,<br />
wie man das Problem hier in den Griff bekommen kann ?</p>
<p>Vielen Dank</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/273913/erledigt-speicherfreigabe-im-binärem-baum-wie-stackoverflow-vermeiden</link><generator>RSS for Node</generator><lastBuildDate>Thu, 27 Aug 2026 21:55:28 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/273913.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 15 Sep 2010 14:27:45 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to [Erledigt] Speicherfreigabe im binärem Baum - Wie StackOverFlow vermeiden? on Wed, 15 Sep 2010 16:58:38 GMT]]></title><description><![CDATA[<p>Hallo ihr C++-Freunde,<br />
ich hab mal eine Frage an die Fachkundigen Leute hier.</p>
<p>Im Rahmen einer Semesterarbeit muss ich eine Datenstruktur erstellen, die Elemente sequenziell anordnet und dabei sowohl Speicher- als auch Laufzeit- effizient in Bezug auf die Konkatenation arbeitet. Der Name dieser Datenstruktur soll &quot;Sequence&quot; sein</p>
<p>Um das zu realisieren wurde intern mit einem Baum gearbeitet,<br />
der ähnlich einem binären Baum arbeitet.</p>
<p>Der Aufbau usw. ist alles in Ordnung und funktioniert soweit einwandfrei. Allerdings gibt es ein Problem im Destruktor bzw. bei der Speicherfreigabe.<br />
Der Baum besteht aus Elementen der Klasse &quot;SequenceNode&quot; die sich wiederum einen Referenzzähler merken um feststellen zu können ob es noch Verweise auf dieses Objekt gibt bzw. ob das Objekt gelöscht werden kann. Stirbt jetzt einer dieser Knoten muss er seinem rechten und linken Nachfolger natürlich mitteilen, dass es eine Referenz weniger gibt, die auf sie zeigt.</p>
<p>Wenn wir uns folgenden Code ansehen</p>
<pre><code class="language-cpp">{
Sequence&lt;unsigned&gt; s1; 

for(unsigned ui = 1; ui &lt;= 10000000; ++ui) 
    s1 = s1 + ui
std::cout &lt;&lt; &quot;ende&quot; &lt;&lt; std::endl;
}
</code></pre>
<p>Es wird eine Sequenz mit 10Mio Einträgen erstellt. Danach wird &quot;ende&quot; auf dem Bildschirm ausgegeben und am Ende des Blockes wird die Sequenz gelöscht.<br />
Es wird also der Destruktor von &quot;Sequence&quot; aufgerufen.</p>
<pre><code class="language-cpp">~Sequence()
{ 
    if(m_Root != 0) 
       m_Root-&gt;addRefCount(-1); 
}
</code></pre>
<p>Die Sequenz verwaltet einen Pointer auf ein Wurzelelement des internen Baums.<br />
Diesem Wurzelelement muss nun mitgeteilt werden, dass es eine Referenz weniger gibt.</p>
<p>Die Methode addRefCount befindet sich in der Klasse SequenceNode</p>
<pre><code class="language-cpp">void addRefCount(int value)
        {
            m_RefCount += value;
            if(m_RefCount &lt; 1)
                delete this;
        }
</code></pre>
<p>Sobald hier also der Referenzzähler &lt; 1 wird, wir das Objekt gelöscht und ruft den eigenen Destruktor auf.</p>
<pre><code class="language-cpp">~SequenceNode()
        {
            if(m_Left != 0)
                m_Left-&gt;addRefCount(-1);
            if(m_Right != 0)
                m_Right-&gt;addRefCount(-1);
        }
</code></pre>
<p>Dabei kommt es bei 10 Mio Elementen zu einer tiefen Rekursion,<br />
da jeder sterbende Knoten seinem rechten und linken Nachfolger mitteilen muss das es eine Referenz weniger gibt, und die ggf. dann ihren Nachfolgern usw.</p>
<p>Frage ist jetzt, wie man die Destruktoren so umschreiben kann,<br />
das es zu keinem StackOverflow mehr kommt, aber der Speicherplatz korrekt freigegeben wird.</p>
<p>Hat jemand eine Idee/ Tipp für mich,<br />
wie man das Problem hier in den Griff bekommen kann ?</p>
<p>Vielen Dank</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1952978</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1952978</guid><dc:creator><![CDATA[cocacola88]]></dc:creator><pubDate>Wed, 15 Sep 2010 16:58:38 GMT</pubDate></item><item><title><![CDATA[Reply to [Erledigt] Speicherfreigabe im binärem Baum - Wie StackOverFlow vermeiden? on Wed, 15 Sep 2010 15:19:29 GMT]]></title><description><![CDATA[<p>Mittels eines Stacks lässt sich Rekursion linearisieren, inwiefern das der Aufgabenstellung jetzt entgegenkommt weiss ich nicht.</p>
<p>Hier der Pseudo Code</p>
<pre><code class="language-cpp">void delete_node( SequenceNode* node )
{
   assert( node );

   // Referenzzähler verringern     
   node-&gt;RefCount--;
   if( Node-&gt;RefCount == 0 )
   { 
      // Referenzzähler ist 0, Knoten muss gelöscht werden
      stack NodeStack;
      NodeStack.push( node );

      while( !NodeStack.empty() )
      {
         // oberstes Element vom Stack holen 
         SequenceNode* n = NodeStack.pop();

         if( n-&gt;Left ) 
         {
            // Referenzzähler des linken Child Node verringern und ggf. auf Stack legen
            n-&gt;Left-&gt;RefCount--;
            if( n-&gt;Left-&gt;RefCount == 0 ) NodeStack.push( n-&gt;Left );
         }
         if( n-&gt;Right )
         {
            // Referenzzähler des rechten Child Node verringern und ggf. auf Stack legen
            n-&gt;Right-&gt;RefCount--;
            if( n-&gt;Right-&gt;RefCount == 0 ) NodeStack.push( n-&gt;Right );
         }
         // Knoten löschen 
         delete n;
      }
   }
}
</code></pre>
<p>Edit: Statt eines stacks geht auch irgendein anderer Container, dessen Laufzeitverhalten vielleicht besser ist <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /> Die Reihenfolge des Löschens spielt ja keine Rolle, da ginge auch eine einfach verkettete Liste</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1953008</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1953008</guid><dc:creator><![CDATA[DocShoe]]></dc:creator><pubDate>Wed, 15 Sep 2010 15:19:29 GMT</pubDate></item><item><title><![CDATA[Reply to [Erledigt] Speicherfreigabe im binärem Baum - Wie StackOverFlow vermeiden? on Wed, 15 Sep 2010 16:57:48 GMT]]></title><description><![CDATA[<p>Vielen Dank für deine schnelle Antwort.<br />
Durch das Beispiel konnte ich mein Problem relativ schnell lösen<br />
und hab jetzt keinen StackOverFlow mehr und damit hat sich mein Problem dann erledigt.</p>
<p>Für alle die es interessiert</p>
<pre><code class="language-cpp">~Sequence()
       {
            abcd(m_Root);
       }
</code></pre>
<pre><code class="language-cpp">void abcd(SequenceNode&lt;Type&gt;* seqNode)
        {
            seqNode-&gt;addRefCount(-1);
            if(seqNode-&gt;getRefCount() == 0)
            {
                stack&lt; SequenceNode&lt;Type&gt;* &gt; NodeStack;
                NodeStack.push(seqNode);

                while(!NodeStack.empty())
                {
                    SequenceNode&lt;Type&gt;* node = NodeStack.top();
                    NodeStack.pop();

                    if(node-&gt;getLeft())
                    {
                        node-&gt;getLeft()-&gt;addRefCount(-1);
                        if(node-&gt;getLeft()-&gt;getRefCount() == 0)
                            NodeStack.push(node-&gt;getLeft());
                    }

                    if(node-&gt;getRight())
                    {
                        node-&gt;getRight()-&gt;addRefCount(-1);
                        if(node-&gt;getRight()-&gt;getRefCount() == 0)
                            NodeStack.push(node-&gt;getRight());
                    }

                    delete node;
                }
            }
        }
</code></pre>
<p>Und in SequenceNode ist der Destruktor nun leer und</p>
<pre><code class="language-cpp">void addRefCount(int value)
        {
            m_RefCount += value;
        }
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1953062</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1953062</guid><dc:creator><![CDATA[cocacola88]]></dc:creator><pubDate>Wed, 15 Sep 2010 16:57:48 GMT</pubDate></item></channel></rss>