<?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[Zugriffsverletzung: Destruktor mit std::vector&amp;lt;&amp;gt;::erase()]]></title><description><![CDATA[<p>Hallo zusammen, mein Programm sieht etwa folgendermassen aus (hatte kürzlich ein ähnliches Problem) - beim Destruktor, wenn ich den Speicher mit delete freigebe, tritt eine Zugriffsverletzung auf.</p>
<pre><code class="language-cpp">class Enemy
{
    public:
    sf::Sprite *Barrel;
    Enemy(const Enemy &amp;Origin);
    ~Enemy();
};

Enemy::Enemy(const Enemy &amp;Origin) // Kopierkonstruktor
{
    if (/* je nach Gegner */)
       Barrel = new sf::Sprite(Image);
    else
       Barrel = NULL;
}

Enemy::~Enemy() // Destruktor
{
   // Ausgabe 2 (Iterator)..
   // Ausgabe 3 (Member von *this)..
   delete Barrel;
}
</code></pre>
<pre><code class="language-cpp">// global
std::vector&lt;Enemy&gt; Enemies;
std::vector&lt;Enemy&gt;::iterator it;
</code></pre>
<pre><code class="language-cpp">// in einer Funktion
   it = ThisMap-&gt;Enemies.begin() + /* ... */;
   // Ausgabe 1 (Iterator)..
   ThisMap-&gt;Enemies.erase(it);
</code></pre>
<p>Wenn ich mir die Klassenmember des Iterators (bei Ausgabe 1) ansehe, stimmt noch alles. Dann lösche ich diese Klasse mit <em>erase()</em>, und es wird automatisch der Destruktor <em>Enemy::~Enemy()</em> aufgerufen. Dort (Ausgabe 2) habe ich jedoch völlig andere Werte für den Iterator, wie kann das sein? Ich denke, zuerst wird die Klasse destruiert und erst dann aus dem Vektor entfernt, geschieht das umgekehrt?...<br />
Wenn ich dann schlussendlich noch Ausgabe 3 anschaue und im Destruktor die klasseneigenen Member betrachte, sind es wiederum andere Werte, und zwar die des letzten Vektor-Elementes... Das würde heissen, der Destruktor wird vom letzten Element aufgerufen, was ja nur durch erase() oder pop_back() - die ich aber nicht auf das letzte Element anwende - möglich wäre. Das Merkwürdige daran ist, das letzte Element im Vektor ist nachher immer noch das gleiche.<br />
Weil immer der Destruktor des letzten Elementes aufgerufen wird, wird delete ja mehrfach angewandt, was zu der Zugriffsverweigerung führt.</p>
<p>Ich kann es mir jedoch nicht erklären, wieso immer der Destruktor des letzten Elementes aufgerufen wird, zumal ich die Iteratoren ja noch ausgeben lasse (bei Ausgabe 1 stimmen die Werte noch). Geschieht da intern im Vektor etwas, oder woran könnte das liegen?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/211725/zugriffsverletzung-destruktor-mit-std-vector-lt-gt-erase</link><generator>RSS for Node</generator><lastBuildDate>Thu, 08 Oct 2026 16:06:58 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/211725.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 26 Apr 2008 15:54:37 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Zugriffsverletzung: Destruktor mit std::vector&amp;lt;&amp;gt;::erase() on Sat, 26 Apr 2008 15:54:37 GMT]]></title><description><![CDATA[<p>Hallo zusammen, mein Programm sieht etwa folgendermassen aus (hatte kürzlich ein ähnliches Problem) - beim Destruktor, wenn ich den Speicher mit delete freigebe, tritt eine Zugriffsverletzung auf.</p>
<pre><code class="language-cpp">class Enemy
{
    public:
    sf::Sprite *Barrel;
    Enemy(const Enemy &amp;Origin);
    ~Enemy();
};

Enemy::Enemy(const Enemy &amp;Origin) // Kopierkonstruktor
{
    if (/* je nach Gegner */)
       Barrel = new sf::Sprite(Image);
    else
       Barrel = NULL;
}

Enemy::~Enemy() // Destruktor
{
   // Ausgabe 2 (Iterator)..
   // Ausgabe 3 (Member von *this)..
   delete Barrel;
}
</code></pre>
<pre><code class="language-cpp">// global
std::vector&lt;Enemy&gt; Enemies;
std::vector&lt;Enemy&gt;::iterator it;
</code></pre>
<pre><code class="language-cpp">// in einer Funktion
   it = ThisMap-&gt;Enemies.begin() + /* ... */;
   // Ausgabe 1 (Iterator)..
   ThisMap-&gt;Enemies.erase(it);
</code></pre>
<p>Wenn ich mir die Klassenmember des Iterators (bei Ausgabe 1) ansehe, stimmt noch alles. Dann lösche ich diese Klasse mit <em>erase()</em>, und es wird automatisch der Destruktor <em>Enemy::~Enemy()</em> aufgerufen. Dort (Ausgabe 2) habe ich jedoch völlig andere Werte für den Iterator, wie kann das sein? Ich denke, zuerst wird die Klasse destruiert und erst dann aus dem Vektor entfernt, geschieht das umgekehrt?...<br />
Wenn ich dann schlussendlich noch Ausgabe 3 anschaue und im Destruktor die klasseneigenen Member betrachte, sind es wiederum andere Werte, und zwar die des letzten Vektor-Elementes... Das würde heissen, der Destruktor wird vom letzten Element aufgerufen, was ja nur durch erase() oder pop_back() - die ich aber nicht auf das letzte Element anwende - möglich wäre. Das Merkwürdige daran ist, das letzte Element im Vektor ist nachher immer noch das gleiche.<br />
Weil immer der Destruktor des letzten Elementes aufgerufen wird, wird delete ja mehrfach angewandt, was zu der Zugriffsverweigerung führt.</p>
<p>Ich kann es mir jedoch nicht erklären, wieso immer der Destruktor des letzten Elementes aufgerufen wird, zumal ich die Iteratoren ja noch ausgeben lasse (bei Ausgabe 1 stimmen die Werte noch). Geschieht da intern im Vektor etwas, oder woran könnte das liegen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1498620</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1498620</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sat, 26 Apr 2008 15:54:37 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverletzung: Destruktor mit std::vector&amp;lt;&amp;gt;::erase() on Sat, 26 Apr 2008 16:40:39 GMT]]></title><description><![CDATA[<p>hi!<br />
zunächst mal: klassen können nicht gelöscht oder destruiert werden. du meinst objekte oder instanzen.</p>
<p>Nexus schrieb:</p>
<blockquote>
<p>Wenn ich mir die Klassenmember des Iterators (bei Ausgabe 1) ansehe, stimmt noch alles. Dann lösche ich diese Klasse mit erase(), und es wird automatisch der Destruktor Enemy::~Enemy() aufgerufen. Dort (Ausgabe 2) habe ich jedoch völlig andere Werte für den Iterator, wie kann das sein? Ich denke, zuerst wird die Klasse destruiert und erst dann aus dem Vektor entfernt, geschieht das umgekehrt?...</p>
</blockquote>
<p>wenn du tatsächlich auf so ein wissen angewiesen bist, dann ist die primäre informationquelle für dich der standard. dort findest du spezifikationen zu allen memberfunktionen und dem interface der standardcontainer. und wenn dort etwas nicht definiert ist (so wie, was geschieht zuerst, der iterator invalidiert oder das element gelöscht), dann ist das ein hinweis an dich, deinen code nicht von einer bestimmten reihenfolge abhängig zu machen (weil es überall anders aussehen könnte).</p>
<p>für dein verständnisproblem hilft es wahrscheinlich, dir vorzustellen, wie vector intern normalerweise aufgebaut ist: als einfach zusammenhängender, mit new allozierter, speicher.<br />
dann stell dir vor, du machst das manuell:</p>
<pre><code class="language-cpp">typedef Enemy* iterator;

Enemy* vector = new Enemy[100];
iterator it = vector + 20;
</code></pre>
<p>wie würdest du nun das element, auf den der iterator zeigt, löschen?<br />
du müsstest es aus dem array herausnehmen, und letztendlich alle anderen elemente, die nach dem element, auf das der iterator zeigt, kommen, eines nach hinten kopieren. der iterator könnte die ganze zeit auf dieselbe stelle zeigen.<br />
wenn du aber alle elemente &quot;eins nach hinten kopieren&quot; musst, musst du alle elemente irgendwann zerstören und sie an einer neuen position (eins dahinter) wieder zum leben erwecken.</p>
<p>wenn du mit dynamischen speicher arbeitest, solltest du smart-pointer verwenden (hier: boost::shared_ptr oder std::tr1::shared_ptr), damit du dir das problem mit dem &quot;doppelten delete&quot; ersparst und exceptionsicher bist. ansonsten schau dir die Regel der großen Drei &quot;rule of the big three&quot; an, und implementiere deinen copy-konstruktor richtig!</p>
<pre><code class="language-cpp">struct Foo
{
   Sprite* Barrel;
   Foo (Foo const&amp; other)
   {
      Barrel = new Sprite(other.Barrel);
   }
   Foo&amp; operator = (Foo const&amp; other)
   {
      Foo tmp(other);
      swap (Barrel, tmp.Barrel);
      return *this;
   }
   ~Foo ()
   {
      delete Barrel;
   }
};

//und mit shared_ptr sieht es so aus
struct Enemy
{
   std::tr1::shared_ptr&lt;Sprite&gt; Barrel;
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1498643</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1498643</guid><dc:creator><![CDATA[queer_boy]]></dc:creator><pubDate>Sat, 26 Apr 2008 16:40:39 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverletzung: Destruktor mit std::vector&amp;lt;&amp;gt;::erase() on Sat, 26 Apr 2008 18:06:27 GMT]]></title><description><![CDATA[<p>Hallo, erst einmal vielen Dank für die ausführliche Antwort.</p>
<p>Mit &quot;Klassen destruieren&quot; hab ich mich falsch ausgedrückt, ich meinte natürlich Instanzen.</p>
<p>So, wie du das Prinzip mit dem Löschen der dahinterstehenden Elemente und dem folgenden Neu-Erstellen eine Position davor erklärt hast, kann das aber nicht stimmen. Das sehe ich ja nur schon daran, dass der Destruktor nur ein einziges Mal (nicht für alle Elemente dahinter) aufgerufen wird. Er wird zwar aufgerufen, wieso das betroffene Element allerdings das letzte ist, ist mir nach wie vor ein Rätsel. Ich hab den Iterator mehrfach überprüft, er zeigt sowohl vor als auch nach dem Aufruf von <em>erase()</em> auf das richtige Element. Es wird auch das richtige Element aus dem Vektor entfernt, jedoch nicht der richtige Destruktor aufgerufen...</p>
<p>Zu <em>erase()</em> finde ich nirgends genaue Informationen, wie der Algorithmus im Detail funktioniert. Überall ist nur beschrieben, wie er anzuwenden ist, und das mit einfachen Beispielen. Und im Quellcode der Datei &quot;vector&quot; finde ich mich kein bisschen zurecht <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/1498684</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1498684</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sat, 26 Apr 2008 18:06:27 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverletzung: Destruktor mit std::vector&amp;lt;&amp;gt;::erase() on Sat, 26 Apr 2008 18:43:11 GMT]]></title><description><![CDATA[<p>Ein Objekt kann logischerweise nicht mehr zerstört werden, wenn der Speicher bereits freigegeben wurde. Diese Frage beantwortet sich also von selbst. Die Semantik von erase ist im Standard eindeutig beschrieben:<br />
1. erase ruft m mal den Zuweisungsoperator auf, wobei m die Anzahl der Elemente nach dem zu löschenden Bereich ist<br />
Danach wird<br />
2. n mal der Destruktor aufgerufen, wobei n die Anzahl der Elemente im zu löschenden Bereich ist</p>
<p>Die Reihenfolge der Zuweisung ist unbestimmt (wird aber wohl immer aufsteigend sein, weil der Zielbereich ja überlappen kann). Die Reihenfolge der Destruktoraufrufe ist ebenfalls unbestimmt (das geht nur, weil Destruktoren von Elementen keine Exceptions werfen dürfen), wird aber wohl vom höheren Index aus erfolgen: in umgekehrter Reihenfolge der Erzeugung - beginnend also mit dem letzten Element.<br />
Warum wird nicht erst zerstört und dann kopiert (und nochmal zerstört)? Sowohl Zuweisungsoperator als auch Copyctor von Elementen dürfen Exceptions werfen - wirft ein Copyctor eine Exception hätte unser vector aber plötzlich ein Loch: das darf nicht sein.</p>
<p>Es werden also tatsächlich nicht genau die Elemente zerstört, auf die die übergebene Sequenz verweist (wenn sie sich nicht zufällig am Ende befindet).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1498698</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1498698</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sat, 26 Apr 2008 18:43:11 GMT</pubDate></item></channel></rss>