<?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[new und Speicherfreigabe nach exception]]></title><description><![CDATA[<p>Hi,</p>
<p>was passiert mit dem Speicher der von new reserviert wird nach einer exception ? Folgendes Beispiel:</p>
<pre><code class="language-cpp">void __fastcall TForm1::Button2Click(TObject *Sender)
{
 try
  {
   Form2 = 0;  // Bin mir nicht sicher ob man das auf 0 setzen muss ?
   if ( Sender == Button2 )
     {
	  Form2 = new TForm2(this);
	  Form2-&gt;ShowModal();
	 }
   else
	 {
	  Form2 = new TForm2(this, sNewTitel);
	  Form2-&gt;ShowModal();
	 }
   delete Form2;
  }
 catch( exception&amp; e )
  {
   ShowMessage( e.what() );
   if ( Form2 ) delete Form2;  // Ist diese Abfrage überflüssig oder ist das zwingend notwendig ?
  } 
}
//---------------------------------------------------------------------------
</code></pre>
<p>Wenn ich mit new ein neues Objekt (hier ein neues Formular) erzeuge und dann im neuen Objekt, z.B. gleich im C'tor eine Exception werfe, muss ich dann oben im catch()-Block prüfen ob noch ein Verweis auf das Objekt besteht und dann mit delete löschen, oder wird das Objekt automatisch gelöscht und der Speicher wieder freigegeben ?</p>
<p>Im Debugger hab ich gesehen, dass nach einer Exception Form2 == 0 ist, aber kann ich da immer von aus gehen oder ist es besser immer auf 0 zu prüfen und dann zu deleten ? Und was ist mit dem reservierten Speicher, ist der dann wieder komplett freigegeben ?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/237398/new-und-speicherfreigabe-nach-exception</link><generator>RSS for Node</generator><lastBuildDate>Wed, 23 Sep 2026 10:14:35 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/237398.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 28 Mar 2009 11:11:18 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to new und Speicherfreigabe nach exception on Sat, 28 Mar 2009 11:11:18 GMT]]></title><description><![CDATA[<p>Hi,</p>
<p>was passiert mit dem Speicher der von new reserviert wird nach einer exception ? Folgendes Beispiel:</p>
<pre><code class="language-cpp">void __fastcall TForm1::Button2Click(TObject *Sender)
{
 try
  {
   Form2 = 0;  // Bin mir nicht sicher ob man das auf 0 setzen muss ?
   if ( Sender == Button2 )
     {
	  Form2 = new TForm2(this);
	  Form2-&gt;ShowModal();
	 }
   else
	 {
	  Form2 = new TForm2(this, sNewTitel);
	  Form2-&gt;ShowModal();
	 }
   delete Form2;
  }
 catch( exception&amp; e )
  {
   ShowMessage( e.what() );
   if ( Form2 ) delete Form2;  // Ist diese Abfrage überflüssig oder ist das zwingend notwendig ?
  } 
}
//---------------------------------------------------------------------------
</code></pre>
<p>Wenn ich mit new ein neues Objekt (hier ein neues Formular) erzeuge und dann im neuen Objekt, z.B. gleich im C'tor eine Exception werfe, muss ich dann oben im catch()-Block prüfen ob noch ein Verweis auf das Objekt besteht und dann mit delete löschen, oder wird das Objekt automatisch gelöscht und der Speicher wieder freigegeben ?</p>
<p>Im Debugger hab ich gesehen, dass nach einer Exception Form2 == 0 ist, aber kann ich da immer von aus gehen oder ist es besser immer auf 0 zu prüfen und dann zu deleten ? Und was ist mit dem reservierten Speicher, ist der dann wieder komplett freigegeben ?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1687305</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1687305</guid><dc:creator><![CDATA[Trial]]></dc:creator><pubDate>Sat, 28 Mar 2009 11:11:18 GMT</pubDate></item><item><title><![CDATA[Reply to new und Speicherfreigabe nach exception on Sat, 28 Mar 2009 11:53:20 GMT]]></title><description><![CDATA[<p>Ja, du musst den Speicher - jedenfalls so wie du es machst - wieder manuell freigeben. Eleganter wäre es, das Ganze über <a href="http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization" rel="nofollow">RAII</a> zu lösen.</p>
<p>Außerdem empfehle ich die beiden Artikel aus dem Magazin zu Exceptions.</p>
<p>Und die Überprüfung</p>
<pre><code class="language-cpp">if(myPointer != 0){delete myPointer;}
</code></pre>
<p>bringt nichts, das ist äquivalent zu</p>
<pre><code class="language-cpp">delete myPointer;
</code></pre>
<p>weil delete auf einem Nullpointer einfach nichts macht.</p>
<p>Felix</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1687333</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1687333</guid><dc:creator><![CDATA[Phoemuex]]></dc:creator><pubDate>Sat, 28 Mar 2009 11:53:20 GMT</pubDate></item><item><title><![CDATA[Reply to new und Speicherfreigabe nach exception on Sat, 28 Mar 2009 12:06:56 GMT]]></title><description><![CDATA[<p>Generell ist die Abfrage auf 0 vor einem 'delete' überflüssig, da 'delete' intern schon auf 0 überprüft. Es wird jedoch häufig so programmiert, daß man nach dem delete die Variable auf 0 setzt (um evtl. doppeltes Freigeben zu vermeiden).</p>
<p>Und zur eigentlichen Frage bzgl. new und exceptions:<br />
Wenn beim Erzeugen eines Objektes im Konstruktor schon eine Exception geworfen wird, so wird ja die Variable (bei dir 'Form2') ja gar nicht erst gefüllt, d.h. die Exception wird ausgelöst und direkt in den catch-Zweig gesprungen (bzw. wenn dieser nicht vorhanden wäre, dann im Aufruf-Stack nach oben weitergereicht). Du brauchst dich dann um die Freigabe nicht mehr kümmern, da der angeforderte Speicher intern wieder gelöscht wird (sonst gäbe es ja bei jeder dieser Exceptions ein Speicherleck).</p>
<p>Es könnte bei deinem Code aber auch passieren, daß erst im Form2-&gt;ShowModal() eine Ausnahme (excpetion) auftritt und dann müßtest du jedoch die Freigabe selber durchführen.</p>
<p>Desweiteren solltest du bei lokalen Aufrufen einer anderen Klasse (bzw. Form) auch eine lokale Variable benutzen (der BCB legt zwar für jedes Formular eine Variable an, diese wird jedoch nur zwingend von der &quot;Project.cpp&quot; benötigt).</p>
<p>Und zuletzt noch:<br />
du mußt auch zwischen den verschiedenen Exception-Klassen unterscheiden:<br />
- std::exception Basis-Klasse der Standard C++ Library<br />
- Exception Basis-Klasse der VCL</p>
<p>Hier noch, wie ich es programmiert hätte:</p>
<pre><code class="language-cpp">void __fastcall TForm1::Button2Click(TObject *Sender)
{
  TForm2 form = 0; // lokale Variable
  try
  {
    if ( Sender == Button2 )
    {
      form = new TForm2(this);
    }
    else
    {
      form = new TForm2(this, sNewTitel); // s. Anmerkung unten
    }

    form-&gt;ShowModal();
  }
  catch( exception&amp; e )
  {
    ShowMessage( e.what() );
  }

  delete form;
}
</code></pre>
<p>Die Klassen und Variablennamen solltest du natürlich aussagekräftiger benennen.<br />
Und bzgl. der beiden Konstruktoren bei TForm2 hätte ich einfach nur einen definiert und nachträglich dann die Eigenschaft 'NewTitle' gesetzt.</p>
<p>Ich hoffe, ich habe damit deine Frage(n) zufriedenstellend beantwortet?</p>
<p>P.S. Der generelle Hinweis auf RAII ist zwar gut, jedoch in diesem Fall nicht von Interesse. RAII benutzt man innerhalb von Konstruktoren, um dort angeforderten Speicher (bzw. Ressourcen) wieder freizugeben (wenn eine Exception passiert). Der Speicher für das eigentliche Objekt wird jedoch (wie ich oben schon geschrieben habe) selbständig bei einer möglichen Exception wieder freigegeben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1687341</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1687341</guid><dc:creator><![CDATA[Th]]></dc:creator><pubDate>Sat, 28 Mar 2009 12:06:56 GMT</pubDate></item><item><title><![CDATA[Reply to new und Speicherfreigabe nach exception on Sat, 28 Mar 2009 12:09:30 GMT]]></title><description><![CDATA[<p>Wenn du komplexere Abhängigkeiten hast, lohnt sich das genannte RAII schnell einmal. Sonst musst du nämlich oftmals einzelne Fälle per <code>if</code> abfragen.<br />
Das <code>new</code> , das fehlschlägt, wird automatisch per <code>delete</code> freigegeben. Jedoch musst du dich selber um zuvor allokierten Speicher kümmern (wenn du zum Beispiel drei Speicheranforderungen hast und die dritte fehlschlägt, müssen die ersten beiden manuell freigegeben werden).</p>
<p>Von daher empfehlen sich <a href="http://magazin.c-plusplus.net/artikel/Schlaue%20Zeiger%20-%20Boost%20Smart%20Pointer" rel="nofollow">Smart Pointer</a> - hier sollte <code>boost::scoped_ptr</code> reichen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1687347</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1687347</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sat, 28 Mar 2009 12:09:30 GMT</pubDate></item><item><title><![CDATA[Reply to new und Speicherfreigabe nach exception on Sat, 28 Mar 2009 12:16:05 GMT]]></title><description><![CDATA[<p>Th schrieb:</p>
<blockquote>
<p>P.S. Der generelle Hinweis auf RAII ist zwar gut, jedoch in diesem Fall nicht von Interesse. RAII benutzt man innerhalb von Konstruktoren, um dort angeforderten Speicher (bzw. Ressourcen) wieder freizugeben (wenn eine Exception passiert). Der Speicher für das eigentliche Objekt wird jedoch (wie ich oben schon geschrieben habe) selbständig bei einer möglichen Exception wieder freigegeben.</p>
</blockquote>
<p>Gut, wenn im Konstruktor eine Exception fliegt, wird der Speicher natürlich wieder freigegeben. Aber trotzdem kann man RAII doch nicht nur in Konstruktoren einsetzen. Ich hatte bei dem Post des OP nicht beachtet, dass Form2 keine lokale Variable war, deswegen war der Vorschlag dort wirklich unsinnig, aber wenn form wie in deinem Beispiel lokal ist, kann man RAII einfach dazu benutzen, für einen aufzuräumen (und spart sich damit das delete am Ende).</p>
<p>Felix</p>
<p>EDIT: Nexus war schneller <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="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1687352</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1687352</guid><dc:creator><![CDATA[Phoemuex]]></dc:creator><pubDate>Sat, 28 Mar 2009 12:16:05 GMT</pubDate></item><item><title><![CDATA[Reply to new und Speicherfreigabe nach exception on Sat, 28 Mar 2009 13:28:14 GMT]]></title><description><![CDATA[<p>Hallo zusammen,</p>
<p>erstmal vielen Dank für Eure Hilfe. Ein paar Fragen habe ich noch:</p>
<p>Th schrieb:</p>
<blockquote>
<p>Es könnte bei deinem Code aber auch passieren, daß erst im Form2-&gt;ShowModal() eine Ausnahme (excpetion) auftritt und dann müßtest du jedoch die Freigabe selber durchführen.</p>
</blockquote>
<p>D.h. einen eigenen try-catch-Block in Form2, oder meinst Du was anderes ?</p>
<p>Th schrieb:</p>
<blockquote>
<p>Desweiteren solltest du bei lokalen Aufrufen einer anderen Klasse (bzw. Form) auch eine lokale Variable benutzen (der BCB legt zwar für jedes Formular eine Variable an, diese wird jedoch nur zwingend von der &quot;Project.cpp&quot; benötigt).</p>
</blockquote>
<p>Das habe ich jetzt noch nicht verstanden. Ich muss ja Form2 über Unit2 includieren, warum dann noch eine lokale Variable ?</p>
<p>Mit</p>
<pre><code class="language-cpp">TForm2 form = 0;
</code></pre>
<p>bekomme ich folgende Fehlermeldung:<br />
[C++ Fehler] Unit1.cpp(34): E2459 Klassen im VCL-Stil müssen mit dem Operator new erstellt werden</p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/12954">@Nexus</a> und Phoemuex: Danke für den Hinweis, aber mit Smart Pointern und RAII habe ich mich noch nicht beschäftigt. Das muss ich mir alles noch reinziehen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /> .</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1687404</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1687404</guid><dc:creator><![CDATA[Trial]]></dc:creator><pubDate>Sat, 28 Mar 2009 13:28:14 GMT</pubDate></item><item><title><![CDATA[Reply to new und Speicherfreigabe nach exception on Sat, 28 Mar 2009 15:14:15 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">void __fastcall TForm1::Button2Click(TObject *Sender) 
{
  if ( Sender == Button2 ) 
  { 
    boost::scoped_ptr&lt;TForm2&gt; Form2 = new TForm2(this); 
    Form2-&gt;ShowModal(); 
  } 
  else 
  { 
    boost::scoped_ptr&lt;TForm2&gt; Form2 = new TForm2(this, sNewTitel); 
    Form2-&gt;ShowModal(); 
  } 
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1687486</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1687486</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Sat, 28 Mar 2009 15:14:15 GMT</pubDate></item><item><title><![CDATA[Reply to new und Speicherfreigabe nach exception on Sat, 28 Mar 2009 15:56:20 GMT]]></title><description><![CDATA[<p>Shade Of Mine schrieb:</p>
<blockquote>
<pre><code class="language-cpp">void __fastcall TForm1::Button2Click(TObject *Sender) 
{
  if ( Sender == Button2 ) 
  { 
    boost::scoped_ptr&lt;TForm2&gt; Form2 = new TForm2(this); 
    Form2-&gt;ShowModal(); 
  } 
  else 
  { 
    boost::scoped_ptr&lt;TForm2&gt; Form2 = new TForm2(this, sNewTitel); 
    Form2-&gt;ShowModal(); 
  } 
}
</code></pre>
</blockquote>
<p>Nein, scoped_ptr&lt;&gt; ist für TForm und Derivate unangebracht:<br />
<a href="http://docs.embarcadero.com/products/rad_studio/radstudio2007/RS2007_helpupdates/HUpdate4/DE/html/delphivclwin32/Forms_TCustomForm_Release.html" rel="nofollow">TCustomForm::Release()</a></p>
<p>RAD Studio 2007-Dokumentation schrieb:</p>
<blockquote>
<p>Mit Release können Sie das Formular aus dem Speicher entfernen.</p>
<p>Release gibt das Formular erst frei, nachdem die Ausführung der Ereignisbehandlungsroutinen des Formulars und seiner untergeordneten Komponenten beendet ist. Die Methode stellt auch sicher, dass alle Botschaften in der Ereigniswarteschlange des Formulars vor dessen Freigabe bearbeitet werden. Jede Ereignisbehandlungsroutine für das Formular oder für dessen untergeordnete Objekte sollte Release anstelle von Free (Delphi) oder Delete (C++) benutzen. Ansonsten kann ein Speicherzugriffsfehler auftreten.<br />
Anmerkung: Release gibt die Steuerung sofort an die aufrufende Routine zurück und wartet nicht, bis das Formular freigegeben wird.</p>
</blockquote>
<p>Im Übrigen entsteht kein Speicherleck, da der Owner von Form2, der im Konstruktor übergeben wird, das Objekt in jedem Fall freigibt - allerdings erst bei seiner eigenen Destruktion.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1687512</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1687512</guid><dc:creator><![CDATA[audacia]]></dc:creator><pubDate>Sat, 28 Mar 2009 15:56:20 GMT</pubDate></item><item><title><![CDATA[Reply to new und Speicherfreigabe nach exception on Sat, 28 Mar 2009 17:08:51 GMT]]></title><description><![CDATA[<p>audacia schrieb:</p>
<blockquote>
<p>Nein, scoped_ptr&lt;&gt; ist für TForm und Derivate unangebracht:</p>
</blockquote>
<p>Dann ist das delete vom OP also auch falsch, oder?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1687545</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1687545</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Sat, 28 Mar 2009 17:08:51 GMT</pubDate></item><item><title><![CDATA[Reply to new und Speicherfreigabe nach exception on Sat, 28 Mar 2009 19:19:32 GMT]]></title><description><![CDATA[<p>Ja.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1687618</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1687618</guid><dc:creator><![CDATA[audacia]]></dc:creator><pubDate>Sat, 28 Mar 2009 19:19:32 GMT</pubDate></item></channel></rss>