<?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[Anfängerfrage: mit new nicht auf den heap]]></title><description><![CDATA[<p>Hallo zusammen,</p>
<p>ich programmiere auf einem stark ressourcenlimitierten embedded system. Da der Zugriff auf den externen Speicher länger dauert, habe ich es bisher vermieden Objekte dynamisch anzulegen, damit alles auf dem internen Speicher landet.<br />
Der Code wird nun jedoch arg unübersichtlich, wenn mir weiterhin verwehrt bleibt Objekte dynamisch zur Laufzeit zu generieren und ihnen dann mitzuteilen von welchem Typ sie sind.</p>
<p>Gibt es die Möglichkeit ein Objekt bspw. mit einem strategy pattern ohne new zu erzeugen, so dass es auf dem Stack landet?</p>
<p>Viele Grüße<br />
Zisko</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/320737/anfängerfrage-mit-new-nicht-auf-den-heap</link><generator>RSS for Node</generator><lastBuildDate>Wed, 22 Jul 2026 14:06:39 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/320737.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 09 Oct 2013 18:40:09 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Wed, 09 Oct 2013 18:40:09 GMT]]></title><description><![CDATA[<p>Hallo zusammen,</p>
<p>ich programmiere auf einem stark ressourcenlimitierten embedded system. Da der Zugriff auf den externen Speicher länger dauert, habe ich es bisher vermieden Objekte dynamisch anzulegen, damit alles auf dem internen Speicher landet.<br />
Der Code wird nun jedoch arg unübersichtlich, wenn mir weiterhin verwehrt bleibt Objekte dynamisch zur Laufzeit zu generieren und ihnen dann mitzuteilen von welchem Typ sie sind.</p>
<p>Gibt es die Möglichkeit ein Objekt bspw. mit einem strategy pattern ohne new zu erzeugen, so dass es auf dem Stack landet?</p>
<p>Viele Grüße<br />
Zisko</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359246</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359246</guid><dc:creator><![CDATA[Zisko]]></dc:creator><pubDate>Wed, 09 Oct 2013 18:40:09 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Wed, 09 Oct 2013 18:50:06 GMT]]></title><description><![CDATA[<p>Zisko schrieb:</p>
<blockquote>
<p>Objekte dynamisch zur Laufzeit zu generieren und ihnen dann mitzuteilen von welchem Typ sie sind.</p>
</blockquote>
<p>Brauchst du das wirklich? Weil wenn ja, dann führt am Heap nichts vorbei.</p>
<p>In meiner Erfahrung braucht man das jedoch nicht wirklich. Es gibt eine Anzahl Klassen und von jeder Klasse will man max. 1 Instanz. Dann lässt sich das über statische Variablen lösen:</p>
<pre><code class="language-cpp">// Header
class Abstract { virtual void f(); };
Abstract *get_it(int id);

// cpp
namespace { // schützt vor Namenskollisionen, nicht wirklich nötig

class StratA : Abstract { ... };
class StratB : Abstract { ... };

StratA strat_a_impl;
StratB strat_b_impl;

}

Abstract *get_it(int id) { return id ? &amp;strat_a_impl : &amp;strat_b_impl; }
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2359251</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359251</guid><dc:creator><![CDATA[heepyheepy]]></dc:creator><pubDate>Wed, 09 Oct 2013 18:50:06 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Wed, 09 Oct 2013 18:56:49 GMT]]></title><description><![CDATA[<p>Viele Compiler bieten <code>alloca()</code> .<br />
Ist aber mit Vorsicht zu genießen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359254</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359254</guid><dc:creator><![CDATA[Caligulaminus]]></dc:creator><pubDate>Wed, 09 Oct 2013 18:56:49 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Wed, 09 Oct 2013 19:00:04 GMT]]></title><description><![CDATA[<p>Caligulaminus schrieb:</p>
<blockquote>
<p>Viele Compiler bieten <code>alloca()</code> .</p>
</blockquote>
<p>Ja, alloca eignet sich perfekt um etwas von einer Funktion zurückzugeben <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359257</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359257</guid><dc:creator><![CDATA[allola]]></dc:creator><pubDate>Wed, 09 Oct 2013 19:00:04 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Wed, 09 Oct 2013 19:02:46 GMT]]></title><description><![CDATA[<p>Grundlegend habe ich ein Klasse A in der sich eine Klasse B befindet. Von Klasse B gibt es zwei Varianten, die sich unterscheiden. Beim erzeugen von A möchte ich dem Konstruktor eine Variable übergeben, die dann die richtige Variante von B erzeugt.</p>
<p>Derzeit löse ich das so, dass ich für A unterschiedliche namespaces verwende und je nach namespace wird dann ein A mit Variante 1 von B erzeugt oder A mit Variante 2.</p>
<p>Es funktioniert, aber ist nicht grade die eleganteste Lösung.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359258</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359258</guid><dc:creator><![CDATA[Zisko]]></dc:creator><pubDate>Wed, 09 Oct 2013 19:02:46 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Wed, 09 Oct 2013 19:03:58 GMT]]></title><description><![CDATA[<p>allola schrieb:</p>
<blockquote>
<p>eignet sich perfekt um etwas von einer Funktion zurückzugeben <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
</blockquote>
<p>Habe ich nie behauptet.<br />
In der Hinsicht besteht kein Unterschied zu automatischen Objekten.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359259</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359259</guid><dc:creator><![CDATA[Caligulaminus]]></dc:creator><pubDate>Wed, 09 Oct 2013 19:03:58 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Wed, 09 Oct 2013 19:56:57 GMT]]></title><description><![CDATA[<blockquote>
<p>ressourcenlimitierten embedded system</p>
</blockquote>
<p>Normalerweise schoepft man auf solchen Systemen nicht alle Features von C++ aus. Und wenn ich Strategiepattern im Zusammenhang mit ressourcenlimitierten Systemen hoere, dann schrillen schon mal alle Alarmglocken bei mir.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359276</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359276</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Wed, 09 Oct 2013 19:56:57 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Wed, 09 Oct 2013 20:43:23 GMT]]></title><description><![CDATA[<p>Zisko schrieb:</p>
<blockquote>
<p>Derzeit löse ich das so, dass ich für A unterschiedliche namespaces verwende und je nach namespace wird dann ein A mit Variante 1 von B erzeugt oder A mit Variante 2.</p>
</blockquote>
<p>Das kannst du auch billiger mit nem Template bekommen.<br />
Ist aber immer noch net wirklich elegant, weil's dann immer noch zwei verschiedene A sind.</p>
<p>Im Prinzip brauchst du bloss Speicher reservieren der gross genug für das grössere der beiden B ist, und passend aligned für beide.<br />
In C++11 geht das mit <code>aligned_storage</code><br />
<a href="http://en.cppreference.com/w/cpp/types/aligned_storage" rel="nofollow">http://en.cppreference.com/w/cpp/types/aligned_storage</a></p>
<p>Ohne C++11 kann man sich auch selbst so ein Template schreiben - wenn man sich damit zufrieden gibt dass es für eine bestimmte Plattform funktioniert ist das recht einfach.<br />
Dann schnappt man sich die Adresse von dem Ding, und erstellt mit placement-new dort das gewünschte Objekt. Zum Löschen darf man den Destruktor direkt über den Passenden Zeiger aufrufen (&quot; <code>ptr-&gt;~B();</code> &quot;).</p>
<p>Und natürlich kannst du <code>boost::variant</code> verwenden. So lange du den Typ nur beim Initialisieren des Variants festlegst und danach nie mehr änderst &quot;lebt&quot; das enthaltene Objekt auch direkt &quot;im&quot; Variant.<br />
Und falls du den Variant nicht gleich in der Initializer-List passend initialisieren kannst, kannst du das ganze noch mit boost::optional kombinieren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359286</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359286</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Wed, 09 Oct 2013 20:43:23 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 10:07:43 GMT]]></title><description><![CDATA[<p>Zisko schrieb:</p>
<blockquote>
<p>Hallo zusammen,</p>
<p>ich programmiere auf einem stark ressourcenlimitierten embedded system. Da der Zugriff auf den externen Speicher länger dauert, habe ich es bisher vermieden Objekte dynamisch anzulegen, damit alles auf dem internen Speicher landet.<br />
Der Code wird nun jedoch arg unübersichtlich, wenn mir weiterhin verwehrt bleibt Objekte dynamisch zur Laufzeit zu generieren und ihnen dann mitzuteilen von welchem Typ sie sind.</p>
<p>Gibt es die Möglichkeit ein Objekt bspw. mit einem strategy pattern ohne new zu erzeugen, so dass es auf dem Stack landet?</p>
<p>Viele Grüße<br />
Zisko</p>
</blockquote>
<p>was heißt externer Speicher? new reserviert Speicher im RAM, ich denke mal dafür wird der interne RAM verwendet.<br />
Normale Variablen landen am Stack, und der befindet sich auch im RAM.<br />
So gesehen sollte new, mal abgesehen vom Verwaltungsaufwand, nicht viel langsamer sein als Variablen am Stack. Zumindest der Zugriff sollte genau gleich schnell sein!</p>
<p>Ansonsten reservier dir halt statisch ein großes Bytearray, das landet in der Data Sektion und sollte im RAM landen. Und dann definier dir dein eigenes new/delete welches in eben diesem Bytearray Speicher reserviert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359632</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359632</guid><dc:creator><![CDATA[ggdgfd]]></dc:creator><pubDate>Fri, 11 Oct 2013 10:07:43 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 10:15:24 GMT]]></title><description><![CDATA[<p>grob vereinfachtes RAM Layout, auch auf vielen embedded systems:</p>
<pre><code>text: Der ausführbare Programmcode
data: statische und globale Variablen
heap: zur dynamischen Speicherverwaltung
stack: für Funktionsaufrufe und lokale Variablen
</code></pre>
<p>Ich behaupte Mal, dass für stack und heap der gleiche Speicher verwendet.<br />
Ansosnten kannst du das vielleicht dem Compiler mitteilen.<br />
So gesehen dürfte das Zugreifen auf stack (lokale Variablen) und heap (dyn. Speicher) nicht viel Zeitunterschied machen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359633</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359633</guid><dc:creator><![CDATA[sdfsdfsdfs]]></dc:creator><pubDate>Fri, 11 Oct 2013 10:15:24 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 10:49:07 GMT]]></title><description><![CDATA[<p>Wäre es nicht evtl. zweckmäßig, einen pseudo-free-store zu verwenden, der auf dem Stack liegt?<br />
In main wird einfach eine Funktion aufgerufen, die entsprechend auf dem Stack ein hinreichend großes Array anlegt und dann die Funnktion für den restlichen Programmablauf aufruft. Zugriff auf diesen Pseuo-free-store kriegt man dann über überladene new/delete-Operatoren (ggf. mit einer eigenen placement-Form, um die Standardfunktionen weiter nutzen zu können).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359635</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359635</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Fri, 11 Oct 2013 10:49:07 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 14:36:07 GMT]]></title><description><![CDATA[<blockquote>
<p>Wäre es nicht evtl. zweckmäßig, einen pseudo-free-store zu verwenden, der auf dem Stack liegt?</p>
</blockquote>
<p>Meinst du so etwas in der Richtung:</p>
<pre><code>template&lt;class T, std::size_t N&gt;
class static_allocator
{
    typename std::aligned_storage&lt;sizeof(T), std::alignment_of&lt;T&gt;::value&gt;::type data[N];
    std::size_t m_size = 0;

public:

    std::size_t available() const { return N - m_size; }

    template&lt;typename ...Args&gt;
    T* create(Args&amp;&amp;... args)
    {
        if( m_size == N )
         // Fehlerbehandlung

        return new(data+m_size++) T(std::forward&lt;Args&gt;(args)...);
    }

    ~static_vector() 
    {
        for(std::size_t pos = 0; pos &lt; m_size; ++pos)
            static_cast&lt;T*&gt;(static_cast&lt;const void*&gt;(data+pos))-&gt;~T();
    }
};
</code></pre>
<p>(angepasster Code <a href="http://en.cppreference.com/w/cpp/types/aligned_storage" rel="nofollow">von cppreference</a>, ungetestet)<br />
Allerdings bin ich mir im Unklaren, ob das überhaupt standardkonform ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359681</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359681</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Fri, 11 Oct 2013 14:36:07 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 15:41:13 GMT]]></title><description><![CDATA[<p>Nö, das funktioniert so nicht da der Allocator selbst nicht den Speicher besitzen darf/kann.<br />
Mann könnte die Arena seperat anlegen dem Allocator eine Referenz auf diese mitgeben.</p>
<p>Anzumerken ist aber dass das mit der Arena massive Probleme macht wenn Container regelmäßig Speicher freigeben &amp; dafür neuen allozieren. (vector/string etc)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359703</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359703</guid><dc:creator><![CDATA[Ethon]]></dc:creator><pubDate>Fri, 11 Oct 2013 15:41:13 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 15:53:20 GMT]]></title><description><![CDATA[<blockquote>
<p>stark ressourcenlimitierten embedded system</p>
</blockquote>
<p>Benenne doch mal das System.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359705</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359705</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Fri, 11 Oct 2013 15:53:20 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 15:59:04 GMT]]></title><description><![CDATA[<blockquote>
<p>Nö, das funktioniert so nicht da der Allocator selbst nicht den Speicher besitzen darf/kann.</p>
</blockquote>
<p>Das war auch kein serienreifer Allokator, sondern eine Richtungsangabe. Man kann den Pool statisch machen.</p>
<blockquote>
<p>Anzumerken ist aber dass das mit der Arena massive Probleme macht wenn Container regelmäßig Speicher freigeben &amp; dafür neuen allozieren.</p>
</blockquote>
<p>Wieso das?<br />
Die Vergabe des Speichers muss (gerade auf einem Ressourcenknappen System) stark optimiert werden, um möglichst keine ungenutzten Lücken zu erzeugen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359707</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359707</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Fri, 11 Oct 2013 15:59:04 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 17:43:25 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<p>Wäre es nicht evtl. zweckmäßig, einen pseudo-free-store zu verwenden, der auf dem Stack liegt?<br />
In main wird einfach eine Funktion aufgerufen, die entsprechend auf dem Stack ein hinreichend großes Array anlegt und dann die Funnktion für den restlichen Programmablauf aufruft. Zugriff auf diesen Pseuo-free-store kriegt man dann über überladene new/delete-Operatoren (ggf. mit einer eigenen placement-Form, um die Standardfunktionen weiter nutzen zu können).</p>
</blockquote>
<p>aber ich frage nochmal: warum soll der Stack im &quot;schnellen&quot; internen Speicher liegen, während der Heap im &quot;langsamen&quot; externen Speicher liegt.<br />
Hier wäre doch mal der erste Ansatzpunkt.</p>
<p>@Arcoth: Wieso über Templates?<br />
Definier doch eine eigene Version von new/new[]/delete/delete[]. Letztlich hast du dann 2 Funktionen die die Logik implementieren und diese können für alle Datentypen verwendet werden.<br />
Und die holen sich den Speicher von einem vorher reservierten Speicherbereich von der stack oder data Sektion - je nachdem was nun im &quot;schnellen&quot; Speicher landet.<br />
Um die ganzen Details wie CTOR und DTOR aufrufen kümmert sich der Compiler.<br />
Und die Strategie fürs Allokieren sollte schon etwas intelligenter sein. Um nur 2 Dinge zu nennen: es gibt Fragmentierung und Ausrichtung zu beachten.<br />
Ausrichtung ist auf vielen Systemen gegeben, wenn die zurückgegebene Adresse auf 4 oder 8 byte ausgerichtet ist.<br />
Und gegen Fragmentierung gibt es einige Algorithmen wie z.B. den Buddy Allokator.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359719</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359719</guid><dc:creator><![CDATA[cdycycycy]]></dc:creator><pubDate>Fri, 11 Oct 2013 17:43:25 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 18:03:06 GMT]]></title><description><![CDATA[<p>Arcoth schrieb:</p>
<blockquote>
<blockquote>
<p>Anzumerken ist aber dass das mit der Arena massive Probleme macht wenn Container regelmäßig Speicher freigeben &amp; dafür neuen allozieren.</p>
</blockquote>
<p>Wieso das?<br />
Die Vergabe des Speichers muss (gerade auf einem Ressourcenknappen System) stark optimiert werden, um möglichst keine ungenutzten Lücken zu erzeugen.</p>
</blockquote>
<p>Naja, zb:</p>
<pre><code>std::string foo = &quot;Hello&quot;;
foo += &quot; World!&quot;;
</code></pre>
<p>Hier wird foo vermutlich beim Anhängen von &quot; World!&quot; wachsen müssen. In der Arena gibt es keine Möglichkeit richtig sinnvoll Speicher zurückzugeben also wird der Speicher für &quot;Hello&quot; brach liegen.</p>
<p>Finde eine Arena extrem interessant wenn man viele kleine, gleichgroße Objekte erzeugt (zb. std::list, std::map etc) - dann kann man die freigegebenen Objekte einfach speichern und recyclen. Vor allem werden die Container dadurch sauschnell (die Objekte liegen ja hintereinander im Speicher) - hab mal multimap mit queue verglichen - multimap war mit einem Allocator locker 10x so schnell.</p>
<p>Aber general-purpose taugt das imho reichlich wenig.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359724</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359724</guid><dc:creator><![CDATA[Ethon]]></dc:creator><pubDate>Fri, 11 Oct 2013 18:03:06 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 20:43:04 GMT]]></title><description><![CDATA[<p>Ich stelle mir gerade vor, dass man in den Lücken sozusagen eine linked-list führen könnte, dann mehrere Bins für unterschiedliche Größen hat, in denen der erste freie Speicherblock dieser oder etwas größerer Größe vermerkt ist (also ein Zeiger auf den Node der Linked-List in der Lücke), und dann schaut man erstmal in den Bins bei einer Anfrage, wenn da nix ist, dann hängt man hinten an. Bei Freigabe ersetzt man dann den im passenden Bin vermerkten Wert, sodass man nicht erst die Liste langlaufen muss. Also wird der Speicher &quot;von hinten wiederbenutzt&quot;. Irgendwie so, könnte sowas klappen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359744</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359744</guid><dc:creator><![CDATA[decimad]]></dc:creator><pubDate>Fri, 11 Oct 2013 20:43:04 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 20:48:54 GMT]]></title><description><![CDATA[<p>Ja, so geht das. Nur leider macht malloc das genauso, man gewinnt also keine Performance. Für Performance nimmt man einfach eine Arena und nimmt die paar Löcher in Kauf um dafür mehr Speed zu kriegen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359745</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359745</guid><dc:creator><![CDATA[ich bin ein bin]]></dc:creator><pubDate>Fri, 11 Oct 2013 20:48:54 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 20:54:40 GMT]]></title><description><![CDATA[<p>Irgendwie hatte ich jetzt den Eindruck gewonnen, dass malloc dann doch etwas mehr zu tun hat, als ein popelige if != nullptr und ein paar writes... Zumal es doch auch blockieren kann in Multithreading-Umgebungen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359746</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359746</guid><dc:creator><![CDATA[decimad]]></dc:creator><pubDate>Fri, 11 Oct 2013 20:54:40 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 21:22:47 GMT]]></title><description><![CDATA[<p>decimad schrieb:</p>
<blockquote>
<p>Ich stelle mir gerade vor, dass man in den Lücken sozusagen eine linked-list führen könnte, dann mehrere Bins für unterschiedliche Größen hat, in denen der erste freie Speicherblock dieser oder etwas größerer Größe vermerkt ist (also ein Zeiger auf den Node der Linked-List in der Lücke), und dann schaut man erstmal in den Bins bei einer Anfrage, wenn da nix ist, dann hängt man hinten an. Bei Freigabe ersetzt man dann den im passenden Bin vermerkten Wert, sodass man nicht erst die Liste langlaufen muss. Also wird der Speicher &quot;von hinten wiederbenutzt&quot;. Irgendwie so, könnte sowas klappen?</p>
</blockquote>
<p>Je nachdem. Was will man haben?</p>
<p>Alle malloc/free-Strategien (außer sie schlicht ans BS hochzureichen) kann man auch locker benutzen, um in einem Funktionslokalen Array rumzuallokieren.</p>
<p>Ich fange mal an mit denen, die absolut geizig sind. Mikrocontroller, Code aus dem Arduino-Projekt. Der Rechner schluckt unter Last gerade mal 60 milli-Ampere, perfekt, um meine neue Heizung zu steuern. 2k RAM, es werden nur triviale Programme drauf laufen. FALLS mal malloc/free benutzt werden muss, dann extrem speicherparend, Laufzeit hingegen ist egal. Kein Problem, wenn der Schrittmitor, der die Heizung hochdreht, wenn ich die Tür aufmache, eine zehntel Sekunde später angeht.</p>
<pre><code>/* Copyright (c) 2002, 2004, 2010 Joerg Wunsch
   Copyright (c) 2010  Gerben van den Broeke
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.

   * Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
     distribution.

   * Neither the name of the copyright holders nor the names of
     contributors may be used to endorse or promote products derived
     from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot;
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.
*/

/* $Id: malloc.c 2149 2010-06-09 20:45:37Z joerg_wunsch $ */

#include &lt;stdlib.h&gt;
#include &quot;sectionname.h&quot;
#include &quot;stdlib_private.h&quot;

#include &lt;avr/io.h&gt;

/*
 * Exported interface:
 *
 * When extending the data segment, the allocator will not try to go
 * beyond the current stack limit, decreased by __malloc_margin bytes.
 * Thus, all possible stack frames of interrupt routines that could
 * interrupt the current function, plus all further nested function
 * calls must not require more stack space, or they'll risk to collide
 * with the data segment.
 */

/* May be changed by the user only before the first malloc() call.  */

size_t __malloc_margin = 128;
char *__malloc_heap_start = &amp;__heap_start;
char *__malloc_heap_end = &amp;__heap_end;

char *__brkval;
struct __freelist *__flp;

ATTRIBUTE_CLIB_SECTION
void *
malloc(size_t len)
{
	struct __freelist *fp1, *fp2, *sfp1, *sfp2;
	char *cp;
	size_t s, avail;

	/*
	 * Our minimum chunk size is the size of a pointer (plus the
	 * size of the &quot;sz&quot; field, but we don't need to account for
	 * this), otherwise we could not possibly fit a freelist entry
	 * into the chunk later.
	 */
	if (len &lt; sizeof(struct __freelist) - sizeof(size_t))
		len = sizeof(struct __freelist) - sizeof(size_t);

	/*
	 * First, walk the free list and try finding a chunk that
	 * would match exactly.  If we found one, we are done.  While
	 * walking, note down the smallest chunk we found that would
	 * still fit the request -- we need it for step 2.
	 *
	 */
	for (s = 0, fp1 = __flp, fp2 = 0;
	     fp1;
	     fp2 = fp1, fp1 = fp1-&gt;nx) {
		if (fp1-&gt;sz &lt; len)
			continue;
		if (fp1-&gt;sz == len) {
			/*
			 * Found it.  Disconnect the chunk from the
			 * freelist, and return it.
			 */
			if (fp2)
				fp2-&gt;nx = fp1-&gt;nx;
			else
				__flp = fp1-&gt;nx;
			return &amp;(fp1-&gt;nx);
		}
		else {
			if (s == 0 || fp1-&gt;sz &lt; s) {
				/* this is the smallest chunk found so far */
				s = fp1-&gt;sz;
				sfp1 = fp1;
				sfp2 = fp2;
			}
		}
	}
	/*
	 * Step 2: If we found a chunk on the freelist that would fit
	 * (but was too large), look it up again and use it, since it
	 * is our closest match now.  Since the freelist entry needs
	 * to be split into two entries then, watch out that the
	 * difference between the requested size and the size of the
	 * chunk found is large enough for another freelist entry; if
	 * not, just enlarge the request size to what we have found,
	 * and use the entire chunk.
	 */
	if (s) {
		if (s - len &lt; sizeof(struct __freelist)) {
			/* Disconnect it from freelist and return it. */
			if (sfp2)
				sfp2-&gt;nx = sfp1-&gt;nx;
			else
				__flp = sfp1-&gt;nx;
			return &amp;(sfp1-&gt;nx);
		}
		/*
		 * Split them up.  Note that we leave the first part
		 * as the new (smaller) freelist entry, and return the
		 * upper portion to the caller.  This saves us the
		 * work to fix up the freelist chain; we just need to
		 * fixup the size of the current entry, and note down
		 * the size of the new chunk before returning it to
		 * the caller.
		 */
		cp = (char *)sfp1;
		s -= len;
		cp += s;
		sfp2 = (struct __freelist *)cp;
		sfp2-&gt;sz = len;
		sfp1-&gt;sz = s - sizeof(size_t);
		return &amp;(sfp2-&gt;nx);
	}
	/*
	 * Step 3: If the request could not be satisfied from a
	 * freelist entry, just prepare a new chunk.  This means we
	 * need to obtain more memory first.  The largest address just
	 * not allocated so far is remembered in the brkval variable.
	 * Under Unix, the &quot;break value&quot; was the end of the data
	 * segment as dynamically requested from the operating system.
	 * Since we don't have an operating system, just make sure
	 * that we don't collide with the stack.
	 */
	if (__brkval == 0)
		__brkval = __malloc_heap_start;
	cp = __malloc_heap_end;
	if (cp == 0)
		cp = STACK_POINTER() - __malloc_margin;
	if (cp &lt;= __brkval)
	  /*
	   * Memory exhausted.
	   */
	  return 0;
	avail = cp - __brkval;
	/*
	 * Both tests below are needed to catch the case len &gt;= 0xfffe.
	 */
	if (avail &gt;= len &amp;&amp; avail &gt;= len + sizeof(size_t)) {
		fp1 = (struct __freelist *)__brkval;
		__brkval += len + sizeof(size_t);
		fp1-&gt;sz = len;
		return &amp;(fp1-&gt;nx);
	}
	/*
	 * Step 4: There's no help, just fail. :-/
	 */
	return 0;
}

ATTRIBUTE_CLIB_SECTION
void
free(void *p)
{
	struct __freelist *fp1, *fp2, *fpnew;
	char *cp1, *cp2, *cpnew;

	/* ISO C says free(NULL) must be a no-op */
	if (p == 0)
		return;

	cpnew = p;
	cpnew -= sizeof(size_t);
	fpnew = (struct __freelist *)cpnew;
	fpnew-&gt;nx = 0;

	/*
	 * Trivial case first: if there's no freelist yet, our entry
	 * will be the only one on it.  If this is the last entry, we
	 * can reduce __brkval instead.
	 */
	if (__flp == 0) {
		if ((char *)p + fpnew-&gt;sz == __brkval)
			__brkval = cpnew;
		else
			__flp = fpnew;
		return;
	}

	/*
	 * Now, find the position where our new entry belongs onto the
	 * freelist.  Try to aggregate the chunk with adjacent chunks
	 * if possible.
	 */
	for (fp1 = __flp, fp2 = 0;
	     fp1;
	     fp2 = fp1, fp1 = fp1-&gt;nx) {
		if (fp1 &lt; fpnew)
			continue;
		cp1 = (char *)fp1;
		fpnew-&gt;nx = fp1;
		if ((char *)&amp;(fpnew-&gt;nx) + fpnew-&gt;sz == cp1) {
			/* upper chunk adjacent, assimilate it */
			fpnew-&gt;sz += fp1-&gt;sz + sizeof(size_t);
			fpnew-&gt;nx = fp1-&gt;nx;
		}
		if (fp2 == 0) {
			/* new head of freelist */
			__flp = fpnew;
			return;
		}
		break;
	}
	/*
	 * Note that we get here either if we hit the &quot;break&quot; above,
	 * or if we fell off the end of the loop.  The latter means
	 * we've got a new topmost chunk.  Either way, try aggregating
	 * with the lower chunk if possible.
	 */
	fp2-&gt;nx = fpnew;
	cp2 = (char *)&amp;(fp2-&gt;nx);
	if (cp2 + fp2-&gt;sz == cpnew) {
		/* lower junk adjacent, merge */
		fp2-&gt;sz += fpnew-&gt;sz + sizeof(size_t);
		fp2-&gt;nx = fpnew-&gt;nx;
	}
	/*
	 * If there's a new topmost chunk, lower __brkval instead.
	 */
	for (fp1 = __flp, fp2 = 0;
	     fp1-&gt;nx != 0;
	     fp2 = fp1, fp1 = fp1-&gt;nx)
		/* advance to entry just before end of list */;
	cp2 = (char *)&amp;(fp1-&gt;nx);
	if (cp2 + fp1-&gt;sz == __brkval) {
		if (fp2 == NULL)
			/* Freelist is empty now. */
			__flp = NULL;
		else
			fp2-&gt;nx = NULL;
		__brkval = cp2 - sizeof(size_t);
	}
}
</code></pre>
<p>Dann gehts über ein klassisches C-malloc/free, das ähnlich ist, aber nicht so geizig, bis zu modernen, die mit vieltausenden Aufrufen pro Sekunde rechnen müssen und wo man viel Speicher hat, nämlich auf PCs. Dann nimmt man zunächst mal einen Buddy-Allocator. Für kleine Größen sagen wir mal unter 256Bytes sogar Linked-Lists. Tollerweise verbraten Linked-Lists quasi null Speicher für allokierte Bereiche, nur die Nicht-Allokierten müssen verlinkt sein. Also im free() kann man die Spoeicherhappen in den dopplet verketteten Ring einhängen. Bei malloc() tut man sie raus und der Anwender kann den Speicher voll nutzen.</p>
<p>Bin gerade dabei, mich ein wenig in Mikrocontroller einzuarbeiten. 2k RAM ist schon ein Brett, anscheinend werden die noch benutzt? Naja, zur Not Heimspiel für mich, mein erster Rechner hatte 1k.</p>
<p>Für Windows-PCs kann man single-threaded gegenüber dem Standard-new/delete meiner Schätzung nach ca ukm Faktor 70 schneller sein. *hihi*, völlig irrelevant leider, weil mans new/delete eh versucht, selten zu benutzen, und wenn man sie benutzt, das Arbeiten auf den Daten ein Hundertfaches kostet.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359747</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359747</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Fri, 11 Oct 2013 21:22:47 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 22:17:15 GMT]]></title><description><![CDATA[<blockquote>
<p>Das war auch kein serienreifer Allokator, sondern eine Richtungsangabe. Man kann den Pool statisch machen.</p>
</blockquote>
<p>Etwas mehr Zeit mit Google verbringen. Es gibt genug Allocator-Ttorials auch mit Arena.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359755</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359755</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Fri, 11 Oct 2013 22:17:15 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Fri, 11 Oct 2013 22:46:33 GMT]]></title><description><![CDATA[<p>Haha, danke für die Einblicke volkard! <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="🙂"
    /><br />
Meine Intention war nur, eine möglichst einfache, möglichst effiziente (ein Blick in ein recht kleines Array sagt alles) Lösung dafür zu finden, dass bei der &quot;Arena&quot; Speicher verkloppt wird. Mit der Arena will man ja Performance rausschlagen, dachte ich, da wäre etwas langsames ja unangebracht. Niemand hat danach gefragt, es war nur ein Gedankenspiel, dass ich da so machte. Ersteinmal ist das ja eine interessante Angelegenheit und zweitens weiß man ja nie, ob es nicht etwas bringt, wenn man sich über gewisse Dinge schonmal Gedanken gemacht hat, wenn man auf Probleme in die Richtung trifft.<br />
Gut, dass Du mich zum Schmunzeln bringst, die &quot;Kunden&quot;-angelegenheit, die mich hier bis eben beschäftigt hat, war zum Haare raufen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359756</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359756</guid><dc:creator><![CDATA[decimad]]></dc:creator><pubDate>Fri, 11 Oct 2013 22:46:33 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Sat, 12 Oct 2013 22:58:16 GMT]]></title><description><![CDATA[<p>Wo wir schon beim Speicher waren... Wozu brauchen STL-Container eigentlich Allokatoren?!<br />
<a href="http://probablydance.com/2013/05/13/4gb-per-vector/" rel="nofollow">http://probablydance.com/2013/05/13/4gb-per-vector/</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359878</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359878</guid><dc:creator><![CDATA[decimad]]></dc:creator><pubDate>Sat, 12 Oct 2013 22:58:16 GMT</pubDate></item><item><title><![CDATA[Reply to Anfängerfrage: mit new nicht auf den heap on Sat, 12 Oct 2013 23:07:22 GMT]]></title><description><![CDATA[<p>decimad schrieb:</p>
<blockquote>
<p>Wo wir schon beim Speicher waren... Wozu brauchen STL-Container eigentlich Allokatoren?!<br />
<a href="http://probablydance.com/2013/05/13/4gb-per-vector/" rel="nofollow">http://probablydance.com/2013/05/13/4gb-per-vector/</a></p>
</blockquote>
<p>Weil mmap *sehr* langsam ist. Erstellen und löschen jedenfalls, da wird jedesmal die interne Addresstabelle verändert, was bedeutet, dass das gesamte Programm gelockt wird, etc. Einmaliges new/delete ist schneller.</p>
<p>Der Ansatz ist gut, vielleicht ein kleiner mmap-Pool für grosse Vektoren <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f60b.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_savoring_food"
      title=":yum:"
      alt="😋"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2359879</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2359879</guid><dc:creator><![CDATA[supermalloc]]></dc:creator><pubDate>Sat, 12 Oct 2013 23:07:22 GMT</pubDate></item></channel></rss>