<?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[Operatorüberladung new, delete - falsche Adressen?]]></title><description><![CDATA[<p>Hallo,<br />
In letzter Zeit beschäftige ich mich ein wenig mit manueller Speicherverwaltung. Nun habe ich vier Funktionen für die Überladung der Operatoren <code>new</code> , <code>new[]</code> , <code>delete</code> und <code>delete[]</code> geschrieben:</p>
<pre><code class="language-cpp">void* operator new(size_t Size)
{
	void* p = malloc(Size);
	std::cerr &lt;&lt; &quot;new      &quot; &lt;&lt; p &lt;&lt; std::endl;
	return p;
}

void* operator new[](size_t Size)
{
	void* p = malloc(Size);
	std::cerr &lt;&lt; &quot;new[]    &quot; &lt;&lt; p &lt;&lt; std::endl;
	return p;
}

void operator delete(void* p)
{
	std::cerr &lt;&lt; &quot;delete   &quot; &lt;&lt; p &lt;&lt; std::endl;
	free(p);
}

void operator delete[](void* p)
{
	std::cerr &lt;&lt; &quot;delete[] &quot; &lt;&lt; p &lt;&lt; std::endl;
	free(p);
}
</code></pre>
<p>Ich möchte bei mir Fehler abfangen, die auf die Verwechslung von <code>delete</code> und <code>delete[]</code> im Programm zurückzuführen sind. Dazu würde ich die Adressen bei der Allokation speichern und zusätzlich merken, ob die []-Version von <code>new</code> angewandt wurde. So weit, so gut - bei skalaren Typen und PODs funktioniert das Ganze gut, ich kann Fehler durch Verwendung der falschen <code>delete</code> -Version erkennen.</p>
<p>Bei Klassentypen jedoch gibt es ein Problem: Je nachdem, welche Version von <code>delete</code> aufgerufen wird, handelt es sich um eine andere Adresse. In den Funktionen mit der Array-Version beinhaltet der Zeiger eine Adresse <strong>vier Byte vor</strong> dem Zeiger der Nicht-Array-Version. Das führt unweigerlich zu Heap Corruptions.</p>
<p>Hat jemand einen Lösungsansatz? Da sich die Zeiger bei skalaren Typen &quot;normal&quot; verhalten, kann ich nicht jedes Mal 4 Byte subtrahieren/addieren. Hier dürfte nicht mal Boost ( <code>is_pod</code> ) helfen, da ja die Typinformation durch <code>void*</code> verloren geht...</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/229382/operatorüberladung-new-delete-falsche-adressen</link><generator>RSS for Node</generator><lastBuildDate>Sat, 04 Apr 2026 05:33:15 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/229382.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 10 Dec 2008 22:45:27 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Wed, 10 Dec 2008 22:54:37 GMT]]></title><description><![CDATA[<p>Hallo,<br />
In letzter Zeit beschäftige ich mich ein wenig mit manueller Speicherverwaltung. Nun habe ich vier Funktionen für die Überladung der Operatoren <code>new</code> , <code>new[]</code> , <code>delete</code> und <code>delete[]</code> geschrieben:</p>
<pre><code class="language-cpp">void* operator new(size_t Size)
{
	void* p = malloc(Size);
	std::cerr &lt;&lt; &quot;new      &quot; &lt;&lt; p &lt;&lt; std::endl;
	return p;
}

void* operator new[](size_t Size)
{
	void* p = malloc(Size);
	std::cerr &lt;&lt; &quot;new[]    &quot; &lt;&lt; p &lt;&lt; std::endl;
	return p;
}

void operator delete(void* p)
{
	std::cerr &lt;&lt; &quot;delete   &quot; &lt;&lt; p &lt;&lt; std::endl;
	free(p);
}

void operator delete[](void* p)
{
	std::cerr &lt;&lt; &quot;delete[] &quot; &lt;&lt; p &lt;&lt; std::endl;
	free(p);
}
</code></pre>
<p>Ich möchte bei mir Fehler abfangen, die auf die Verwechslung von <code>delete</code> und <code>delete[]</code> im Programm zurückzuführen sind. Dazu würde ich die Adressen bei der Allokation speichern und zusätzlich merken, ob die []-Version von <code>new</code> angewandt wurde. So weit, so gut - bei skalaren Typen und PODs funktioniert das Ganze gut, ich kann Fehler durch Verwendung der falschen <code>delete</code> -Version erkennen.</p>
<p>Bei Klassentypen jedoch gibt es ein Problem: Je nachdem, welche Version von <code>delete</code> aufgerufen wird, handelt es sich um eine andere Adresse. In den Funktionen mit der Array-Version beinhaltet der Zeiger eine Adresse <strong>vier Byte vor</strong> dem Zeiger der Nicht-Array-Version. Das führt unweigerlich zu Heap Corruptions.</p>
<p>Hat jemand einen Lösungsansatz? Da sich die Zeiger bei skalaren Typen &quot;normal&quot; verhalten, kann ich nicht jedes Mal 4 Byte subtrahieren/addieren. Hier dürfte nicht mal Boost ( <code>is_pod</code> ) helfen, da ja die Typinformation durch <code>void*</code> verloren geht...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1628545</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1628545</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Wed, 10 Dec 2008 22:54:37 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Wed, 10 Dec 2008 23:16:47 GMT]]></title><description><![CDATA[<p>Also bei mir kommt da genau das gewollte heraus. new[] bekommt immer die größe der elemente + 4 für den count angesagt (mit reinterpret_cast&lt;int*&gt;-1 kann man sich den Count dann auch zu Testzwecken anschauen) und delete[] bekommt ebenselben pointer wieder. Auf dem Weg führt der Compiler dann immer noch +4 bytes und -4 bytes auf den Zeiger aus um den Arraycount vor dem Programm zu verstecken. Bei POD's passiert der ganze Hokuspokus dann wiederum natürlich nicht, da es ja keine Destruktoren aufzurufen gilt... Welchen Compiler setzt du ein?</p>
<p>Grüße,<br />
Michael</p>
<p>PS: Hast Du evtl. probiert etwas mit new alloziertes mit delete[] wieder freizugeben? Das würde ja genau dazu führen, dass der compiler dann 4 Bytes von der Addresse des Zeigers, der aus new (ohne []) stammt &quot;abzieht&quot;.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1628555</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1628555</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Wed, 10 Dec 2008 23:16:47 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Wed, 10 Dec 2008 23:16:50 GMT]]></title><description><![CDATA[<p>Decimad schrieb:</p>
<blockquote>
<p>new[] bekommt immer [...] und delete[] bekommt ebenselben pointer wieder.</p>
</blockquote>
<p>Eben, das Problem taucht ja auf, wenn ich entweder <code>new[]</code> und <code>delete</code> oder <code>new</code> und <code>delete[]</code> auf den gleichen Zeiger ausführe. Diesen Fehlerfall will ich ja abfangen. <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>
<p>Da ich mir alle Adressen von allokiertem Speicherbereich in Containern merke, habe ich mir auch überlegt, jeweils zu schauen, ob ein Eintrag mit 4 Bytes zuvor/danach vorhanden ist. Jedoch ist das nicht ganz sicher, da es ja sein könnte, dass an dieser Position ein anderer Speicherblock stehen würde...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1628559</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1628559</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Wed, 10 Dec 2008 23:16:50 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Wed, 10 Dec 2008 23:20:44 GMT]]></title><description><![CDATA[<p>Naja, dann musst du doch einfach nur new so zurechtbiegen, dass du die info hinterher wiederbekommst, so wie der Compiler das mit seinem Count macht. Du könntest zB. nochmal 4 bytes mehr allozieren, in die unteren 4 dann ne id (0 für kein array, 1 für array) schreiben und dann einfach auf den zurückgegebenen Zeiger 4 draufaddieren. Dann schreibt der Compiler an die addresse den Count und addiert nochmal 4 drauf. In delete kannst du dann einfach -4 machen und hast wieder deine ID. Ich hab das jetzt nicht total durchdacht, aber grundsätzlich würde ich sagen, stellt das doch kein problem dar.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1628561</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1628561</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Wed, 10 Dec 2008 23:20:44 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Wed, 10 Dec 2008 23:43:00 GMT]]></title><description><![CDATA[<p>Grad mal so als proof-of-concept zusammengefrickelt:</p>
<pre><code class="language-cpp">const int noarray = 5;
const int isarray = 11;

void* operator new(size_t Size)
{
    int* p = (int*)malloc(Size+sizeof(int));
	p[0] = noarray;

	std::cerr &lt;&lt; &quot;new      &quot; &lt;&lt; p &lt;&lt; &quot;  size: &quot; &lt;&lt; Size &lt;&lt; std::endl;
    return reinterpret_cast&lt;void*&gt;(p+1);
}

void* operator new[](size_t Size)
{
    int* p = (int*)malloc(Size+sizeof(int));
	p[0] = isarray;

	std::cerr &lt;&lt; &quot;new[]    &quot; &lt;&lt; p_ &lt;&lt; &quot;  size: &quot; &lt;&lt; Size &lt;&lt; std::endl;
    return reinterpret_cast&lt;void*&gt;(p+1);
}

void operator delete(void* p)
{
    int* p_ = reinterpret_cast&lt;int*&gt;(p);
	p_-=1;
	if( *p_ != noarray ) {
		std::cerr &lt;&lt; &quot;ERRROORRRR!!!&quot; &lt;&lt; std::endl;
	}

	std::cerr &lt;&lt; &quot;delete   &quot; &lt;&lt; p_ &lt;&lt; std::endl;
    free(reinterpret_cast&lt;void*&gt;(p_));
}

void operator delete[](void* p)
{   
	int* p_ = reinterpret_cast&lt;int*&gt;(p);
	p_-=1;
	if( *p_ != isarray ) {
		std::cerr &lt;&lt; &quot;ERRROORRRR!!!&quot; &lt;&lt; std::endl;
	}

	std::cerr &lt;&lt; &quot;delete[] &quot; &lt;&lt; p &lt;&lt; std::endl;
    free(reinterpret_cast&lt;void*&gt;(p_));
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1628565</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1628565</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Wed, 10 Dec 2008 23:43:00 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Thu, 11 Dec 2008 17:37:19 GMT]]></title><description><![CDATA[<p>Decimad schrieb:</p>
<blockquote>
<p>Ich hab das jetzt nicht total durchdacht, aber grundsätzlich würde ich sagen, stellt das doch kein problem dar.</p>
</blockquote>
<p>Das Problem ist aber eben, dass ich nicht PODs und Klassentypen unterscheiden kann (zumindest wüsste ich nicht wie). Bei PODs ist die Adresse für einzelne und zusammenhängende Speicherblöcke die gleiche.</p>
<p>Dein Code kann so auch nicht funktionieren, da <code>delete</code> immer zuerst den Destruktor des Objekts aufruft und erst anschliessend <code>operator delete</code> . Wenn der Zeiger nicht direkt auf das Objekt zeigt, kommt es zu einer Zugriffsverletzung.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1628998</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1628998</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Thu, 11 Dec 2008 17:37:19 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Thu, 11 Dec 2008 18:21:31 GMT]]></title><description><![CDATA[<p>Ja, aber wie willst du denn mit dem operator delete verhindern, dass das Objekt falsch zerstört wird vom Compiler vorher?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1629021</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1629021</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Thu, 11 Dec 2008 18:21:31 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Thu, 11 Dec 2008 18:21:08 GMT]]></title><description><![CDATA[<p>Decimad schrieb:</p>
<blockquote>
<p>Warum auch nicht?</p>
</blockquote>
<p>Nexus schrieb:</p>
<blockquote>
<p>Dein Code kann so auch nicht funktionieren, da <code>delete</code> immer zuerst den Destruktor des Objekts aufruft und erst anschliessend <code>operator delete</code> . Wenn der Zeiger nicht direkt auf das Objekt zeigt, kommt es zu einer Zugriffsverletzung.</p>
</blockquote>
]]></description><link>https://www.c-plusplus.net/forum/post/1629026</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1629026</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Thu, 11 Dec 2008 18:21:08 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Thu, 11 Dec 2008 18:25:40 GMT]]></title><description><![CDATA[<p>Also von Nachricht zu Nachricht willst du was anderes. In der ersten Nachricht wunderst du dich, warum die Zeiger unterschiedlich sind. In der 2. Message klingt es so, als hättest du es in der 1. schon gewusst, warum. In der dritten willst du auf einmal etwas verhindern, was mit operator delete nicht verhindern kannst (selbst wenn du wüsstest ob array POD oder nicht), weil es schon geschehen ist?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1629030</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1629030</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Thu, 11 Dec 2008 18:25:40 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Thu, 11 Dec 2008 18:37:30 GMT]]></title><description><![CDATA[<p>Decimad schrieb:</p>
<blockquote>
<p>Also von Nachricht zu Nachricht willst du was anderes. In der ersten Nachricht wunderst du dich, warum die Zeiger unterschiedlich sind. In der 2. Message klingt es so, als hättest du es in der 1. schon gewusst, warum.</p>
</blockquote>
<p>Nicht wirklich. In der ersten stellte ich fest, dass die Adressen bei <code>delete</code> und <code>delete[]</code> bei Klassentypen unterschiedlich seien, und fragte nach einem Lösungsansatz. Im zweiten Post wollte ich dich auf die Verwendung von verschiedenen Speicheroperatoren (z.B. <code>new</code> und <code>delete[]</code> ) aufmerksam machen, da du anscheinend meine Frage falsch verstanden hattest.</p>
<p>Decimad schrieb:</p>
<blockquote>
<p>In der dritten willst du auf einmal etwas verhindern, was mit operator delete nicht verhindern kannst (selbst wenn du wüsstest ob array POD oder nicht), weil es schon geschehen ist?</p>
</blockquote>
<p>Hm, jetzt weiss ich nicht mehr, was du genau damit meinst. Der Fehler in deinem Code besteht darin, dass das Argument des <code>delete</code> -Operators (also <code>ptr</code> in der unten stehenden Codezeile) ein Zeiger auf ein Objekt sein muss, dessen Destruktor dann aufgerufen wird. Bei dir ist das nicht der Fall, weil zuerst noch vier Byte <code>int</code> kommen. Dann wird der Destruktor natürlich nicht richtig bzw. gar nicht aufgerufen und bei dem Versuch entsteht eine Zugriffsverletzung.</p>
<pre><code class="language-cpp">delete ptr;
</code></pre>
<p>Verstehst du mein Problem? Es gibt keinen trivialen Ansatz, der sowohl für PODs und Klassentypen funktioniert, da diese unterschiedlich gehandhabt werden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1629037</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1629037</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Thu, 11 Dec 2008 18:37:30 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Thu, 11 Dec 2008 18:47:56 GMT]]></title><description><![CDATA[<p>Also, ich habe jetzt weiter darüber nachgedacht. Mein nächster Vorschlag wäre, zusätzlich zu dem Identifier noch ein integer davorzupacken, der eine 1 enthält. Dann zerstört delete[] bei nicht POD's wenigstens nur ein Objekt, und das sollte man ja mindestens mit new ohne [] erstellt haben. Dann weißt du außerdem, dass sowohl die parameter, die an beide delete-varianten geschickt werden immer innerhalb von blöcken liegen, die du mit new oder new[] alloziert hast (mehr als 4 Byte wird der Compiler ja nie abziehen, aber die hast du ja eh draufaddiert) kannst also in deiner Liste von alloziert Blöcken nachschauen)<br />
Den Array- oder nicht Array-Identifier sollte man sich dann ja sowieso sparen (Weil man vom Zeiger nicht direkt schließen kann, wo der steht), das kommt einfach in die Liste der allozierten Blöcke. Ansonsten müsstest du den Identifier ja sogar zweimal davorpacken, damit du sicher in einem der beiden Integer im Speicher landest.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1629038</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1629038</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Thu, 11 Dec 2008 18:47:56 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Fri, 12 Dec 2008 07:54:11 GMT]]></title><description><![CDATA[<p>So, ich habe jetzt die ultimative Version geschrieben, die für alle Fälle funktioniert.<br />
Wenn du delete[] auf ein durch ein nicht-[] new erstellten (POD oder nicht) Zeiger aufrufst, dann wird das einzige Objekt korrekt zerstört (falls halt nicht POD) und anschließend auch noch ein Fehler ausgegeben! Wenn du delete auf einen mit new[] erstellten POD aufrufst, dann funzt es, wenn es ein nicht-POD war, dann wird halt nur ein Objekt zerstört (das erste im Array), aber immerhin noch eine Fehlermeldung ausgegeben.</p>
<p>Grüße,<br />
Michael</p>
<pre><code class="language-cpp">const int noarray = 5;
const int isarray = 11;

void* operator new(size_t Size)
{
    unsigned int* p = (unsigned int*)malloc(Size+12);
    p[0] = noarray;
    p[1] = noarray | 0xF00;
    p[2] = 1;

    std::cerr &lt;&lt; &quot;new      &quot; &lt;&lt; p &lt;&lt; &quot;  size: &quot; &lt;&lt; Size &lt;&lt; &quot;  returned: &quot; &lt;&lt; p+3 &lt;&lt; std::endl;
    return reinterpret_cast&lt;void*&gt;(p+3);
}

void* operator new[](size_t Size)
{
    unsigned int* p = (unsigned int*)malloc(Size+12);
    p[0] = isarray;
    p[1] = isarray | 0xF00;
    p[2] = 1;

    std::cerr &lt;&lt; &quot;new[]    &quot; &lt;&lt; p &lt;&lt; &quot;  size: &quot; &lt;&lt; Size &lt;&lt; &quot;  returned: &quot; &lt;&lt; p+3 &lt;&lt; std::endl;
    return reinterpret_cast&lt;void*&gt;(p+3);
}

void operator delete(void* p)
{
    unsigned int* p_ = reinterpret_cast&lt;unsigned int*&gt;(p);
    p_-=3;
    if( (*p_&amp;0xFF) == isarray ) {		
        std::cerr &lt;&lt; &quot;ERRROORRRR!!!&quot; &lt;&lt; std::endl;
    }
    if( *p_&amp;0xF00 ) p_-=1;

    std::cerr &lt;&lt; &quot;delete called with   &quot; &lt;&lt; p &lt;&lt; &quot;  freeing: &quot; &lt;&lt; p_ &lt;&lt; std::endl;
    free(reinterpret_cast&lt;void*&gt;(p_));
}

void operator delete[](void* p)
{   
    unsigned int* p_ = reinterpret_cast&lt;unsigned int*&gt;(p);
    p_-=2;
    if( (*p_&amp;0xFF) == noarray ) {
        std::cerr &lt;&lt; &quot;ERRROORRRR!!!&quot; &lt;&lt; std::endl;

    }
    if( *p_ &amp; 0xF00 ) p_ -= 1;

    std::cerr &lt;&lt; &quot;delete[] called with &quot; &lt;&lt; p &lt;&lt; &quot;  freeing: &quot; &lt;&lt; p_ &lt;&lt;  std::endl;
    free(reinterpret_cast&lt;void*&gt;(p_));
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1629100</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1629100</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 12 Dec 2008 07:54:11 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Sat, 13 Dec 2008 15:40:55 GMT]]></title><description><![CDATA[<p>Danke für deine Bemühungen.</p>
<p>Ich hätte aber noch einige Fragen zu deinem Code: Was machst du genau mit der binären Logik ( <code>operator&amp;</code> und <code>operator|</code> )? Und die 5 und 11 sind einfach willkürliche Zahlen? Und was ist mit den Hexadezimalwerten? Auch sonst versteh ich noch nicht ganz alles, ich versuchs mal zu interpretieren.</p>
<p>Allerdings scheint mir das sehr viel Aufwand... Ist das <code>reinterpret_cast</code> en hier eigentlich überall einem definierten Verhalten? Man müsste einfach statt <code>4</code>  <code>sizeof(int)</code> einsetzen, dann sollte es auch portabel sein... Oder man machts gleich mit <code>char</code> .</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1629964</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1629964</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sat, 13 Dec 2008 15:40:55 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Sat, 13 Dec 2008 15:50:52 GMT]]></title><description><![CDATA[<p>Die 5 und 11 sind völlig willkürlich gewählt (aber der folgende Code geht davon aus, dass sie unterschiedlich und kleiner als 256 sind).<br />
Die binäre Logik dient nur dazu, dass ich mir sparen konnte noch zusätzlich zwei konstanten zu definieren. Sie dient hier dazu, zu unterscheiden, ob man beim ersten oder zweiten Typfeld ist. Ja, in den mallocs sollte man 3*sizeof(unsigned int) benutzen anstatt 12. Das reinterpret_cast ist hier im Prinzip das gleiche, wie wenn du das Ergebnis von malloc (void*) in einen bestimmten Zeigertyp umwandelst. Der Code an sich ist definiert. Aber er funktioniert natürlich nur unter der Annahme, das der Compiler seine Verwaltung von dynamischen Feldern eines nicht-POD's so handhabt, wie du es beobachtet hast.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1629968</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1629968</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Sat, 13 Dec 2008 15:50:52 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Sat, 13 Dec 2008 19:37:17 GMT]]></title><description><![CDATA[<p>Decimad schrieb:</p>
<blockquote>
<p>Die binäre Logik dient nur dazu, dass ich mir sparen konnte noch zusätzlich zwei konstanten zu definieren. Sie dient hier dazu, zu unterscheiden, ob man beim ersten oder zweiten Typfeld ist.</p>
</blockquote>
<p>Ich hab mir eben auch überlegt, das mit 3 <code>char</code> s zu machen - der Wertebereich würde ja längstens reichen. Aber wieso unterteilst du die einzelnen <code>int</code> s noch, wenn du sowieso drei belegst?</p>
<p>Decimad schrieb:</p>
<blockquote>
<p>Aber er funktioniert natürlich nur unter der Annahme, das der Compiler seine Verwaltung von dynamischen Feldern eines nicht-POD's so handhabt, wie du es beobachtet hast.</p>
</blockquote>
<p>Hm, ein guter Einwand. Weiss diesbezüglich jemand mehr?</p>
<p>Schlussendlich scheint es mir ein bisschen viel Aufwand zu sein (wovon Teile möglicherweise gar nicht immer definiertes Verhalten sind) - ansonsten lass ich das einfach meine andere Abfrage erledigen (ob der Zeiger, der freigegeben wurde, gültig ist). Dann erhält man zwar eine weniger spezifische Fehlermeldung, aber da die Verwechslung von <code>delete</code> und <code>delete[]</code> wohl nicht sehr häufig vorkommt... <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>
<p>Naja, vorläufig werde ich es trotzdem mit deinem Ansatz versuchen und schauen, ob er sich bewährt. Vielen Dank nochmals. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1630105</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1630105</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sat, 13 Dec 2008 19:37:17 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Sat, 13 Dec 2008 21:24:22 GMT]]></title><description><![CDATA[<p>Wie meinst du das mit dem Unterteilen?<br />
Bezüglich des gewählten Typs. Die 1 muss meiner Meinung nach sowieso in einem int stehen (halt weil delete[] darauf baut), drum machts doch nur mehr Aufwand, den Rest dann noch in char's zu packen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1630128</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1630128</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Sat, 13 Dec 2008 21:24:22 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Sun, 14 Dec 2008 15:37:41 GMT]]></title><description><![CDATA[<p>Decimad schrieb:</p>
<blockquote>
<p>Wie meinst du das mit dem Unterteilen?</p>
</blockquote>
<p>Ich verstehe deinen Ansatz grundsätzlich nicht ganz.</p>
<p>Wenn Speicher allokiert wird, forderst du doch zusätzlich noch Speicher für 3 <code>int</code> s vor dem &quot;normalen&quot; Speicherbereich an. Dann überprüfst du beim Freigeben, ob an den Stellen der vorher allokierten <code>int</code> -Speicherbereiche das Richtige steht (5 bei <code>new</code> , 11 bei <code>new[]</code> ).</p>
<p>Jetzt sagst du, du brauchst die binäre Logik, um herauszufinden, in welchem Typfeld du bist. Das verstehe ich nicht ganz...</p>
<p>Decimad schrieb:</p>
<blockquote>
<p>Bezüglich des gewählten Typs. Die 1 muss meiner Meinung nach sowieso in einem int stehen (halt weil delete[] darauf baut), drum machts doch nur mehr Aufwand, den Rest dann noch in char's zu packen.</p>
</blockquote>
<p>Sorry, welche Funktion hat die 1 in der dritten 4-Byte-Speicherzelle? Einfach als Puffer, da <code>delete[]</code> bei Klassentypen beginnt, vor dem tatsächlichen Speicherbereich zu löschen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1630354</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1630354</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sun, 14 Dec 2008 15:37:41 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Sun, 14 Dec 2008 16:34:36 GMT]]></title><description><![CDATA[<p>Die 1 dient dazu, dass delete[] nicht wild rumzerstört, wenn du ihm ein durch new erstellten Zeiger übergibst (Ansonsten kämst du oftmals gar nicht mehr in deinen selbstdefinierten operator delete[], weil das zerstören schon Speicherzugriffsverletzungen erzeugt hat).<br />
Ich brauche 2 Typfelder, weil ich ja nicht weiß, welchen Zeiger ich in operator delete[] oder delete bekomme (Der Zeiger liegt ja je nach auftretendem Fall 4 byte davor oder nicht). In beiden steht im unteren byte der Typ des Blocks und im zweiten der beiden Typfelder steht zudem im 2. Byte noch, dass es das 2. Byte ist, damit man sicher einen Zeiger für free() basteln kann.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1630381</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1630381</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Sun, 14 Dec 2008 16:34:36 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Sun, 14 Dec 2008 19:32:31 GMT]]></title><description><![CDATA[<p>Okay, ich habe nun einmal einen eigenen Ansatz versucht, bei dem man mit weniger auskommt. Habe ich etwas Wichtiges vergessen? Denn die Fehlererkennung funktioniert so.</p>
<p>Ich allokiere jetzt nur zwei <code>int</code> -Felder vor dem eigentlichen Speicherbereich, auf die ich in den Freigabefunktionen mit <code>ptr[-2]</code> und <code>ptr[-1]</code> bei den Freigabefunktionen zugreife. Da immer zuerst auf <code>ptr[-1]</code> geprüft wird (und dieser Speicherbereich in jedem Falle reserviert wurde), sollte der Zugriff auf Speicher, der einem nicht gehört, vermieden werden.</p>
<pre><code class="language-cpp">const int NoArray = 42;
const int IsArray = 13;
const int Buffer = 1;

void* operator new(size_t Size)
{	
	int* ptr = reinterpret_cast&lt;int*&gt;(malloc(Size + 2*sizeof(int)));

	ptr[0] = NoArray;
	ptr[1] = Buffer;

	return reinterpret_cast&lt;void*&gt;(ptr + 2);
}

void* operator new[](size_t Size)
{
	int* ptr = reinterpret_cast&lt;int*&gt;(malloc(Size + 2*sizeof(int)));

	ptr[0] = IsArray;
	ptr[1] = Buffer;

	return reinterpret_cast&lt;void*&gt;(ptr + 2);
}

void operator delete(void* Pointer)
{
	int* ptr = reinterpret_cast&lt;int*&gt;(Pointer);

	if (ptr[-1] != Buffer || ptr[-2] != NoArray)
		std::cerr &lt;&lt; &quot;/!\\ Fehler!&quot; &lt;&lt; std::endl;
}

void operator delete[](void* Pointer)
{
	int* ptr = reinterpret_cast&lt;int*&gt;(Pointer);

	if (ptr[-1] != Buffer || ptr[-2] != IsArray)
		std::cerr &lt;&lt; &quot;/!\\ Fehler!&quot; &lt;&lt; std::endl;
}
</code></pre>
<p>Einige Dinge verstehe ich trotzdem noch nicht:</p>
<ul>
<li>Wieso muss <code>Buffer</code> genau 1 sein, damit es zu keiner Zugriffsverletzung kommt? Du hast ja auch gesagt, dass dort sowieso eine 1 stehen muss, weil sie für <code>delete[]</code> benötigt wird...</li>
<li>Warum funktioniert das nur mit <code>int</code> (bei <code>char</code> oder <code>short</code> gibt es Zugriffsverletzungen)? Ist das so, weil bei mir <code>int</code> gleich gross wie ein Zeiger ist? Müsste man demnach auch das allgemein halten, wenn man Portabilität gewährleisten will?</li>
<li>Gibt es noch sonstige Stellen, die gefährlich sein könnten (undefiniertes Verhalten etc.)?</li>
</ul>
]]></description><link>https://www.c-plusplus.net/forum/post/1630466</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1630466</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sun, 14 Dec 2008 19:32:31 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Sun, 14 Dec 2008 19:48:52 GMT]]></title><description><![CDATA[<p>Jau, die 1 muss da stehen und ein int sein, weil ja bevor operator delete[] aufgerufen wird, der &quot;compiler&quot; ein int zurückspringt, sich die Anzahl der Elemente rausliest und dann in der Schleife die Destruktoren der Objekte aufruft und anschließend deinen operator delete[] aufruft. Wenn du da 2 in operator new nur 2 chars vorpacken würdest, würde er schonmal 2 bytest aus unalloziertem Speicher lesen. Wenn es 2 shorts wären, würde er beide zu einem int zusammenfassen und diesen integer (der dann ja schon einen ziemlich großen Wert darstellen könnte, weil du ja dann gedacht buffer[0]&lt;&lt;16+buffer[1] da stehen hättest) als Feldanzahl interpretieren (Und dann x Millionen mal einen Destruktor aufrufen, bzw. schon ziemlich am Anfang abschmieren). Die 1 simuliert ja sozusagen ein Feld mit einem Element.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1630479</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1630479</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Sun, 14 Dec 2008 19:48:52 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Sun, 14 Dec 2008 20:01:38 GMT]]></title><description><![CDATA[<p>Ah, jetzt! In dem Feld vorher steht die Anzahl der Elemente... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f4a1.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--light_bulb"
      title=":bulb:"
      alt="💡"
    /></p>
<p>Aber das könnte wahrscheinlich auch von Compiler zu Compiler variieren... Hm, ich glaube, dafür gibts wohl keine wirklich standardkonforme Lösung.<br />
Und es wird doch einfach <code>sizeof(void*)</code> zurückgegangen, und nicht <code>sizeof(int)</code> , oder? Dass das oft das Gleiche ist, ist ja eher Zufall...</p>
<p>Ansonsten, ist mein Code ungefähr brauchbar? Oder wieso ist deiner um einiges komplizierter? <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/1630490</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1630490</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sun, 14 Dec 2008 20:01:38 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Sun, 14 Dec 2008 20:12:06 GMT]]></title><description><![CDATA[<p>Na klar, das ganze Konzept, dass der Compiler den Arraycount in einem int vor dem Array speichert ist natürlich compilerabhängig. Wobei es wohl kaum einen gibt, der das nicht so implementiert. Fraglich wäre nur, ob das in x64-Code dann 64-bit Integer sind... Wobei das ja wiederum eigentlich mit sizeof(int) schon geregelt ist.<br />
Dein Code ist hauptsächlich deshalb schöner, weil du meinen genommen hast und ihn schöner gemacht hast <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /> Ich hatte zuerst die 2 Felder-Idee wegen der 4-byte-Geschichte und dann nachträglich die Idee mit der 1 noch davor und das dann da reingefrickelt.<br />
Woher weißt du, das der Compiler um sizeof(void*) vorspringt und nicht um sizeof(int)? Ich dachte mir halt, da steht also eine Zahl vor, die 4 byte groß ist, also ist es ein int <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /> Alles Annahmen... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1630499</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1630499</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Sun, 14 Dec 2008 20:12:06 GMT</pubDate></item><item><title><![CDATA[Reply to Operatorüberladung new, delete - falsche Adressen? on Sun, 14 Dec 2008 20:20:47 GMT]]></title><description><![CDATA[<p>Decimad schrieb:</p>
<blockquote>
<p>Dein Code ist hauptsächlich deshalb schöner, weil du meinen genommen hast und ihn schöner gemacht hast <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
</blockquote>
<p>Sollte kein Vorwurf sein, nur dank dir hab ich diesen Code ja so hingekriegt. <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>
<p>Nur die Geschichten mit der binären Logik und dem dritten Feld haben mich von Anfang an verwirrt, deshalb habe ich jetzt versucht, ohne sie auszukommen.</p>
<p>Decimad schrieb:</p>
<blockquote>
<p>Woher weißt du, das der Compiler um sizeof(void*) vorspringt und nicht um sizeof(int)? Ich dachte mir halt, da steht also eine Zahl vor, die 4 byte groß ist, also ist es ein int <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /> Alles Annahmen... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
</blockquote>
<p>Nun ja, ich habe mir vorgestellt, dass er halt gerade eine Zelle im Arbeitsspeicher zurückgeht, und eine Adresse benötigt halt <code>sizeof(void*)</code> Bytes (Grösse eines Zeigers). Aber meistens sollte das sowieso gleich der Grösse von <code>int</code> sein... Aber ja, ist halt auch so eine Annahme. So wirklich portabel bringt man das sowieso kaum hin...</p>
<p>Vielen Dank für deine Hilfe, du hast mich echt weitergebracht! <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1630507</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1630507</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sun, 14 Dec 2008 20:20:47 GMT</pubDate></item></channel></rss>