Forum: PC-Programmierung C++ ohne dynamischen Speicher


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Lothar (Gast)


Lesenswert?

Wie kann denn C++ für Embedded genutzt werden, wenn dynamischer Speicher 
verboten ist?

Ist es möglich C++ nur mit globalen Variablen zu nutzen?

So wird ja dynamisch Speicher für eine Klassen-Instanz reserviert:

GraphBox *graphbox = new GraphBox(...);

Und so würde alternativ die Klassen-Instanz dynamisch auf den Stack 
kommen:

int main(void)
{
  ...
  GraphBox graphbox(...);
  ...
}

Aber die Klassen-Instanz graphbox als globale Variable geht nicht, oder? 
Der Konstruktor muss ja dynamisch ausgeführt werden.

In C kann man natürlich für Structs machen:

struct NODE
{
    uint32_t data;
    struct NODE* prev;
    struct NODE* next;
};

#define NODE_MAX    256
static struct NODE Node[NODE_MAX];
static uint32_t Node_idx = 0;

static struct NODE *Node_malloc(void)
{
  if (Node_idx < NODE_MAX)
    return &Node[Node_idx++];
  else
    return NULL;
}

Wahrscheinlich müsste man in C++ new überladen mit ähnlich sowas:

https://www.keil.com/support/man/docs/c51/c51_init_mempool.htm

von foobar (Gast)


Lesenswert?

> Aber die Klassen-Instanz graphbox als globale Variable geht nicht, oder?
> Der Konstruktor muss ja dynamisch ausgeführt werden.

Die Konstruktoren von globalen Instanzen werden vor main ausgeführt, in 
der Reihenfolge der Definition innerhalb eines C-Files - die Reihenfolge 
von verschiedenen C-Files ist nicht definiert.

von progrmr (Gast)


Lesenswert?

foobar schrieb:
>> Aber die Klassen-Instanz graphbox als globale Variable geht nicht, oder?
>> Der Konstruktor muss ja dynamisch ausgeführt werden.
>
> Die Konstruktoren von globalen Instanzen werden vor main ausgeführt, in
> der Reihenfolge der Definition innerhalb eines C-Files - die Reihenfolge
> von verschiedenen C-Files ist nicht definiert.

+ Konstruktoren (und andere Methoden) möglichst constexpr machen, dann 
werden sie zu einem memcpy bei Programmstart.

Statt new kann man evtl. auch placement-new verwenden (muss dann aber 
manuell die dtors aufrufen, weil man delete ja nicht verwenden kann)

von Lothar (Gast)


Lesenswert?

foobar schrieb:
> Die Konstruktoren von globalen Instanzen werden vor main ausgeführt

Aber immer noch run-time, oder? Damit ist die Bedingung nicht erfüllt, 
dass der Compiler den verfügbaren Speicherplatz vorab prüfen kann wie in 
C z.B.

Program Size: data=18.0 xdata=10 code=237

von cppbert3 (Gast)


Lesenswert?

Lothar schrieb:
> Aber die Klassen-Instanz graphbox als globale Variable geht nicht, oder?
> Der Konstruktor muss ja dynamisch ausgeführt werden.

Wieso muss der ctor "dynamisch" ausgefuehrt werden und warum denkst du 
das die Daten einer Klasse zwangsweise auf dem Heap liegen müssen?

Die grösse der Instanz ist zur Kompilezeit klar, sonst wäre so was wie 
placement-new ja gar nicht nutzbar mit Klassen, ausser Exceptions und 
Allokatornutzende Dinge der STL gibt es keinen Heap Zwang in C++
d.h. aber schon das du dich schon stark einschränken musst

von PittyJ (Gast)


Lesenswert?

Wieso ist dynamischer Speicher verboten?
Und ich benutze den auch, um dynamisch meine Objekte zu erzeugen. 
Funktioniert seit Jahren ohne Probleme.

Was ich allerdings nicht mache ist die Objekte wieder frei zugeben. Oder 
innerhalb der Hauptschleife new und delete zu benutzen.

Aber am Anfang die Dinge einmalig mit new zu initialisieren funktioniert 
prima.

von Rolf M. (rmagnus)


Lesenswert?

Lothar schrieb:
> Wie kann denn C++ für Embedded genutzt werden, wenn dynamischer Speicher
> verboten ist?

Es ist nicht grundsätzlich verboten, aber man versucht, es möglichst zu 
vermeiden. Je nach Anwendung kann es ggf. verboten sein. Und es gibt 
viele Anwendungen, wo dynamischer Speicher auch gar nicht nötig ist.

Lothar schrieb:
> foobar schrieb:
>> Die Konstruktoren von globalen Instanzen werden vor main ausgeführt
>
> Aber immer noch run-time, oder?

Kommt drauf an. Wenn sie constexpr sind oder vom Optimizer eliminiert 
werden, dann nicht.

> Damit ist die Bedingung nicht erfüllt, dass der Compiler den verfügbaren
> Speicherplatz vorab prüfen kann wie in C z.B.

Was hat der Speicherplatz damit zu tun? Der ist ja schon da, wie bei 
jeder anderen globalen Variable auch. Der Konstruktor ist lediglich dazu 
da, aus einem vorhandenen "rohen" Speicherbereich durch Initialisierung 
der Membervariablen ein gültiges Objekt zu machen.

: Bearbeitet durch User
von Mitleserin (a.b.) (Gast)


Angehängte Dateien:

Lesenswert?

Das Keyword heisst static

Ein Weg wie sowas konsequent angewendet werden kann, ist hier zu finden:
https://github.com/KonstantinChizhov/Mcucpp

Als Beispiel beigefügt:
ports_.h - mit meinen Modifikatonen:
- Kommentare
- table layout
- SetBitwise, ClearBitwise: mit default template<reg=out,  >

von Lothar (Gast)


Lesenswert?

Rolf M. schrieb:
> Was hat der Speicherplatz damit zu tun? Der ist ja schon da

Kannst Du mal ein Beispiel zeigen wie man eine Klassen-Instanz als 
globale Variable deklariert?

von Lothar (Gast)


Lesenswert?

Mitleserin (a.b.) schrieb:
> Das Keyword heisst static

Schaue ich mir an ...

von Rolf M. (rmagnus)


Lesenswert?

Lothar schrieb:
> Rolf M. schrieb:
>> Was hat der Speicherplatz damit zu tun? Der ist ja schon da
>
> Kannst Du mal ein Beispiel zeigen wie man eine Klassen-Instanz als
> globale Variable deklariert?

Das sieht genau gleich aus wie bei einer lokalen Variable.
Wenn man dein Beispiel hernimmt:

Lothar schrieb:
> int main(void)
> {
>   ...
>   GraphBox graphbox(...);
>   ...
> }

Dann eben:
1
GraphBox graphbox(...);
2
3
int main(void)
4
{
5
  ...
6
}

von Udo S. (urschmitt)


Lesenswert?

PittyJ schrieb:
> Wieso ist dynamischer Speicher verboten?
> Und ich benutze den auch, um dynamisch meine Objekte zu erzeugen.
> Funktioniert seit Jahren ohne Probleme.

Mit welchen µCs?

von PittyJ (Gast)


Lesenswert?

Udo S. schrieb:
> PittyJ schrieb:
>> Wieso ist dynamischer Speicher verboten?
>> Und ich benutze den auch, um dynamisch meine Objekte zu erzeugen.
>> Funktioniert seit Jahren ohne Probleme.
>
> Mit welchen µCs?

Ich habe einen Arm M0 NXP LPC11
Und jetzt noch einen Arm M7 STM32H7

Da ich je nach Konfiguration der Peripherie mal dies oder das brauche, 
werden nur die benötigten Objekte mit new erzeugt.

von Klaus H. (klummel69)


Lesenswert?

Lothar schrieb:
> Wie kann denn C++ für Embedded genutzt werden, wenn dynamischer Speicher
> verboten ist?

"Verboten" ist das falsche Wort.

"Fehleranfällig" ist die Benutzung von dynamischem Speicher vor allem 
wenn dauernd reserviert und freigegeben wird.

Dynamischer Speicher kann super genutzt werden, wenn man zum Beispiel 
nur bei Start dynamischen Speicher allokiert.
Wird die Konfiguration geänert wird einfach alles neu gestartet und neu 
angelegt.

Läuft seid Jahren in embedded Systemen ohne Probleme.

von mh (Gast)


Lesenswert?

Klaus H. schrieb:
> Lothar schrieb:
>> Wie kann denn C++ für Embedded genutzt werden, wenn dynamischer Speicher
>> verboten ist?
>
> "Verboten" ist das falsche Wort.
>
> "Fehleranfällig" ist die Benutzung von dynamischem Speicher vor allem
> wenn dauernd reserviert und freigegeben wird.

Was genau macht dynamischen Speicher im embedded Bereich 
fehleranfälliger?

von Rolf M. (rmagnus)


Lesenswert?

mh schrieb:
> Was genau macht dynamischen Speicher im embedded Bereich
> fehleranfälliger?

Zum Beispiel Speicherfragmentierung. Je kleiner der Speicher, desto 
problematischer wird diese. Da kann es passieren, dass trotz ausreichend 
freiem Speicher keiner mehr verfügbar ist, weil nicht am Stück.
Und bei kritischen Funktionen will ich allgemein nicht, dass die 
Möglichkeit besteht, dass benötigter Speicher nicht allokiert werden 
kann. Man stelle sich ein ESP vor, dem bei einem Bremsmanöver der 
Speicher ausgeht. Deshalb nimmt man da lieber statischen Speicher, so 
dass es mit Sicherheit immer den nötigen Speicher hat.

von A. S. (achs)


Lesenswert?

mh schrieb:
> Was genau macht dynamischen Speicher im embedded Bereich
> fehleranfälliger?

Nicht dynamischer Speicher allgemeinen, sondern die üblichen 
Implementierungen iin C/C++.

Darum baut man sich embedded speziell angepassten dynamischen Speicher. 
Ring-Puffer, Message-Blöcke, priorisierte Zugriffsfunktionen.

Es geht darum, in begrenzter Zeit einen Speicher zu bekommen, 
Fragmentierung zu vermeiden, Diagnose (wie viel frei, welche verloren, 
...) Und zuerst unwichtige Dinge zu stoppen bzw. quasi getrennte "heaps" 
zu haben.

Das erstmalige allokieren per new&co ist ok und sinnvoll, wenn es 
verschiedene Konfigurationen gibt und eine braucht diese Objekte, die 
andere jene. Allerdings ist dann meist ein Neustart notwendig wenn sie 
sich ändert.

von Olaf (Gast)


Lesenswert?

> Was genau macht dynamischen Speicher im embedded Bereich
> fehleranfälliger?

Jedesmal wenn bei deinem Windows die Maus ruckelt weil das System mal 
wieder swapt oder ein verzweifeltes Programm ein Fenster auf macht um 
dir mitzuteilen das etwas nicht richtig geht, tja dann faehrt eine 
Embedded Steuerung vielleicht gerade eine 100kEuro teure Maschine gegen 
die Wand.

Und die Wahrscheinlichkeit das solche Probleme bei einem Microcntroller 
mit 32k Ram auftreten ist groesser als bei einem Desktop mit 16GB.

Olaf

von Johannes S. (jojos)


Lesenswert?

Olaf schrieb:
> tja dann faehrt eine
> Embedded Steuerung vielleicht gerade eine 100kEuro teure Maschine gegen
> die Wand.

dagegen gibt es RTOS mit Prioritäten, eine Steuerungstask hat eine 
höhere Prio als das GUI.
Und man kann mit Memory Pools arbeiten um auch dynamische Sachen zu 
entschärfen. Ethernet mit lwIP läuft z.B. so.

von Rolf M. (rmagnus)


Lesenswert?

Johannes S. schrieb:
> dagegen gibt es RTOS mit Prioritäten, eine Steuerungstask hat eine
> höhere Prio als das GUI.

Komplett anderes Thema. Wenn der dynamische Speicher alle ist, weil die 
GUI ein hübsches Icon geladen hat, bringt deiner Steuerungstask eine 
hohe Priorität auch nix mehr.

> Und man kann mit Memory Pools arbeiten um auch dynamische Sachen zu
> entschärfen. Ethernet mit lwIP läuft z.B. so.

Klar gibt es Mittel, um trotzdem sicher mit dynamischem Speicher zu 
arbeiten. Aber diese müssen im ganzen Programm auch aktiv genutzt 
werden.

von mh (Gast)


Lesenswert?

Rolf M. schrieb:
> Zum Beispiel Speicherfragmentierung. Je kleiner der Speicher, desto
> problematischer wird diese.
Kannst du zeigen warum das allgemein so ist? Oder ist das vielleicht 
doch anwendungsspezifisch? Größe des Speichers, Größe , Häufigkeit und 
Verteilung der Allokationen, ...

A. S. schrieb:
> Nicht dynamischer Speicher allgemeinen, sondern die üblichen
> Implementierungen iin C/C++.
Ok das ist schonmal etwas ganz anderes ...

A. S. schrieb:
> [...]
> Und zuerst unwichtige Dinge zu stoppen bzw. quasi getrennte "heaps"
> zu haben.
Du meinst, das was C++ von Haus aus eingebaut hat (allokator, pmr, ...)?

Olaf schrieb:
> Jedesmal wenn bei deinem Windows die Maus ruckelt weil das System mal
> wieder swapt oder ein verzweifeltes Programm ein Fenster auf macht um
> dir mitzuteilen das etwas nicht richtig geht, tja dann faehrt eine
> Embedded Steuerung vielleicht gerade eine 100kEuro teure Maschine gegen
> die Wand.
Jedes mal wenn das bei mir auf dem HPC-Cluster, sind vielleicht ein paar 
millionen Stunden Rechenzeit verschwendet und ein mehrere millionen € 
Projekt in Verzug. Es geht auch in anderen Bereichen um viel Geld ...

Olaf schrieb:
> Und die Wahrscheinlichkeit das solche Probleme bei einem Microcntroller
> mit 32k Ram auftreten ist groesser als bei einem Desktop mit 16GB.
>
> Olaf
Bei dir vielleicht. Ich hab noch nie auf einem µC ein Problem mit 
dynamischen Speicher gehabt. Allerdings habe ich auf meinen Test 
Rechenknecht letzte Woche mehrfach einen OOM Fehler bekommen.

von mh (Gast)


Lesenswert?

Rolf M. schrieb:
> Klar gibt es Mittel, um trotzdem sicher mit dynamischem Speicher zu
> arbeiten. Aber diese müssen im ganzen Programm auch aktiv genutzt
> werden.

Statisches Speichermanagment muss auch aktiv im ganzen Programm genutzt 
werden?

von Klaus H. (klummel69)


Lesenswert?

mh schrieb:
>> "Fehleranfällig" ist die Benutzung von dynamischem Speicher vor allem
>> wenn dauernd reserviert und freigegeben wird.
> Was genau macht dynamischen Speicher im embedded Bereich
> fehleranfälliger?

Mein Satz war blöd formuliert, die nachfolgenden Beschreibungen 
eindeutiger.

Ein Beispiel aus dem Leben: Ein PC Softwareentwickler sollte ein 
Messalgorithmus für ein Embedded System implementieren.

Seine Lösung:
In einem 1ms Interrupt wurde Speicher allokiert, eine Lookup Tabelle 
erstellt, Berechnungen durchgeführt, der Speicher wieder freigegeben.
Dummerweise kam sich das ganze mit einem zweiten Interrupt (wieder mit 
Speicherallokierung) in die Quere. Alle paar Stunden war der Speicher so 
fragmentiert, dass "unerklärliche" Messwerte rauskamen.

Dynamischer Speicher an sich ist nicht böse oder fehlerhaft.
Seinen Einsatz ergibt einfach weitere Szenarien, die man kennen und 
berücksichtigen sollte.

Auf PCs ggf verschmerzbar, in Autoairbags ggf schmerzerzeugbar.

von Rolf M. (rmagnus)


Lesenswert?

mh schrieb:
> Rolf M. schrieb:
>> Klar gibt es Mittel, um trotzdem sicher mit dynamischem Speicher zu
>> arbeiten. Aber diese müssen im ganzen Programm auch aktiv genutzt
>> werden.
>
> Statisches Speichermanagment muss auch aktiv im ganzen Programm genutzt
> werden?

Nö, das erledigt der Linker. Ein Speichermanagement zur Laufzeit ist bei 
statischem Speicher nicht nötig.

von mh (Gast)


Lesenswert?

Rolf M. schrieb:
> Nö, das erledigt der Linker. Ein Speichermanagement zur Laufzeit ist bei
> statischem Speicher nicht nötig.

Wenn du so argumentierst ... bei mir erledigt das Speichermanagement die 
C++ Standardlib. Wenn du nicht über deinen statischen Speicher 
nachdenken musst, muss ich nicht über meinen dynamischen nachdenken.

von Klaus H. (klummel69)


Lesenswert?

Jetzt geht wieder die Schwarz / Weiss Sicht los. Es geht doch nicht um 
persönliche Vorlieben. Man muss einfach die kritischen Knackpunkte 
kennen.

von mh (Gast)


Lesenswert?

Klaus H. schrieb:
> Jetzt geht wieder die Schwarz / Weiss Sicht los. Es geht doch nicht um
> persönliche Vorlieben. Man muss einfach die kritischen Knackpunkte
> kennen.

Exakt, es ist abhängig von der Anwendung, was die richtige Wahl ist.

von Rolf M. (rmagnus)


Lesenswert?

mh schrieb:
> Rolf M. schrieb:
>> Nö, das erledigt der Linker. Ein Speichermanagement zur Laufzeit ist bei
>> statischem Speicher nicht nötig.
>
> Wenn du so argumentierst ...

Du hast mit der merkwürdigen Argumentation angefangen.

> bei mir erledigt das Speichermanagement die C++ Standardlib.

… deren Funktionen du dafür zur Laufzeit aufrufen musst, um den Speicher 
für deine Daten zu bekommen.
Aber darum ging es eigentlich überhaupt nicht. Es ging um diese Aussage:

Johannes S. schrieb:
> Und man kann mit Memory Pools arbeiten um auch dynamische Sachen zu
> entschärfen. Ethernet mit lwIP läuft z.B. so.

Also um so Dinge wie Memory Pools. Dazu meinte ich:

Rolf M. schrieb:
> Klar gibt es Mittel, um trotzdem sicher mit dynamischem Speicher zu
> arbeiten. Aber diese müssen im ganzen Programm auch aktiv genutzt
> werden.

Sprich: Ich mache nicht einfach nur ein klassisches malloc oder new, 
sondern muss mich dann im gesamten Programm eben mit den Memorypools 
beschäftigen.

: Bearbeitet durch User
von Johannes S. (jojos)


Lesenswert?

man muss nicht unbedingt im ganzen Programm mit MemoryPools kämpfen, 
siehe lwIP. Das kann auch lokal für sich mit einem arbeiten, der Rest 
der SW kann malloc/new benutzen.

von mh (Gast)


Lesenswert?

Rolf M. schrieb:
> mh schrieb:
>> Rolf M. schrieb:
>>> Nö, das erledigt der Linker. Ein Speichermanagement zur Laufzeit ist bei
>>> statischem Speicher nicht nötig.
>>
>> Wenn du so argumentierst ...
>
> Du hast mit der merkwürdigen Argumentation angefangen.
Du hast vorher die merkwürdige Behauptung aufgestellt, dass das Problem 
Speicherfragmentierung größer wird, je kleiner der Speicher.

>> bei mir erledigt das Speichermanagement die C++ Standardlib.
>
> … deren Funktionen du dafür zur Laufzeit aufrufen musst, um den Speicher
> für deine Daten zu bekommen.
Das ist natürlich ein besonders starkes Argument. Was ist der Nachteil 
an den Funktionen? Ich kann dir mindestens einen Vorteil nennen. Sie 
haben einen Rückgabewert. Da kann man rechzeitig drauf reagieren, bevor 
die heiligen 100k€ Maschine etwas dummes anstellt, wenn sie einen 
Segmentation Fault habt.

> Aber darum ging es eigentlich überhaupt nicht. Es ging um diese Aussage:
>
> Johannes S. schrieb:
>> Und man kann mit Memory Pools arbeiten um auch dynamische Sachen zu
>> entschärfen. Ethernet mit lwIP läuft z.B. so.
>
> Also um so Dinge wie Memory Pools. Dazu meinte ich:
>
> Rolf M. schrieb:
>> Klar gibt es Mittel, um trotzdem sicher mit dynamischem Speicher zu
>> arbeiten. Aber diese müssen im ganzen Programm auch aktiv genutzt
>> werden.
>
> Sprich: Ich mache nicht einfach nur ein klassisches malloc oder new,
> sondern muss mich dann im gesamten Programm eben mit den Memorypools
> beschäftigen.
Warum muss man das plötzlich überall machen? Man kann die Pools da 
einsetzen, wo es sinnvoll ist.
Und wo ist das Problem, wenn man sich im ganzen Programm mit Memorypools 
beschäftigen muss? Auf vielen µC gibt es auch "in Hardware" Memorypools 
(xram, yram, usb-ram, intern, extern, ...) mit denen du dich 
beschäftigen musst, wenn du nur statischen Speicher benutzt.

von Rolf M. (rmagnus)


Lesenswert?

mh schrieb:
> Rolf M. schrieb:
>> mh schrieb:
>>> Rolf M. schrieb:
>>>> Nö, das erledigt der Linker. Ein Speichermanagement zur Laufzeit ist bei
>>>> statischem Speicher nicht nötig.
>>>
>>> Wenn du so argumentierst ...
>>
>> Du hast mit der merkwürdigen Argumentation angefangen.
> Du hast vorher die merkwürdige Behauptung aufgestellt, dass das Problem
> Speicherfragmentierung größer wird, je kleiner der Speicher.

Ja, wird es auch, denn Lücken durch allokierte und wieder freigegebene 
Bereiche tun bei 4k Speicher halt mehr weh als bei 16 GB. Außerdem kann 
man bei größerem Speicher komplexere Speichermanager einsetzen, die z.B. 
separate Bereiche für die am häufigsten vorkommenden Größen haben, um 
damit die Speicherfragmentierung gering zu halten. Bei sehr kleinem 
Speicher hat man den Spielraum für sowas nicht.

mh schrieb:
>>> bei mir erledigt das Speichermanagement die C++ Standardlib.
>>
>> … deren Funktionen du dafür zur Laufzeit aufrufen musst, um den Speicher
>> für deine Daten zu bekommen.
> Das ist natürlich ein besonders starkes Argument. Was ist der Nachteil
> an den Funktionen?

Dass sie fehlschlagen können und das Programm dann irgendwie sinnvoll 
damit umgehen muss. Wie ich oben schon geschrieben hab, wäre es 
katastrophal, wenn das ESP beim Bremseingriff aussteigt wegen "out of 
memory".

> Ich kann dir mindestens einen Vorteil nennen. Sie
> haben einen Rückgabewert. Da kann man rechzeitig drauf reagieren, bevor
> die heiligen 100k€ Maschine etwas dummes anstellt, wenn sie einen
> Segmentation Fault habt.

Eben nicht. Man kann nicht rechtzeitig vorher reagieren, sondern erst 
wenn die Allokation fehlschlägt.

> Warum muss man das plötzlich überall machen?
> Man kann die Pools da einsetzen, wo es sinnvoll ist.
> Und wo ist das Problem, wenn man sich im ganzen Programm mit Memorypools
> beschäftigen muss?

Ich schrieb nur, dass man das halt tun muss und es nicht mit einem 
einfachen malloc getan ist.

von mh (Gast)


Lesenswert?

Rolf M. schrieb:
> Ja, wird es auch, denn Lücken durch allokierte und wieder freigegebene
> Bereiche tun bei 4k Speicher halt mehr weh als bei 16 GB. Außerdem kann
> man bei größerem Speicher komplexere Speichermanager einsetzen, die z.B.
> separate Bereiche für die am häufigsten vorkommenden Größen haben, um
> damit die Speicherfragmentierung gering zu halten. Bei sehr kleinem
> Speicher hat man den Spielraum für sowas nicht.
Das hängt immer noch von der Anwendung ab, wie anfällig das 
Speicherallokationsmuster anfällig für Fragmentation ist.

Rolf M. schrieb:
> Wie ich oben schon geschrieben hab, wäre es
> katastrophal, wenn das ESP beim Bremseingriff aussteigt wegen "out of
> memory".
Kannst du den Qeuelltext eines ESP zeigen, damit ich bewerten kann, ob 
es überhaupt einen Vorteil von dynamischen Speicher gibt? Sonst ist es 
ein ziemlich sinnlose Argument für "dynamischer Speicher auf µC ist 
problemantisch (ohne Einschränkung)".

Rolf M. schrieb:
> Eben nicht. Man kann nicht rechtzeitig vorher reagieren, sondern erst
> wenn die Allokation fehlschlägt.
Und wann und wie reagiert man, wenn man nur statischen Speicher nutzt? 
Oder kannst du den maximalen Speicherverbrauch garantieren? Ich kann das 
bei meinen Programmen nicht, zumindest nicht ohne den Speicher massiv 
überdimensionieren zu müssen.

von Rolf M. (rmagnus)


Lesenswert?

mh schrieb:
> Das hängt immer noch von der Anwendung ab, wie anfällig das
> Speicherallokationsmuster anfällig für Fragmentation ist.

Ja, natürlich tut es das.

> Rolf M. schrieb:
>> Wie ich oben schon geschrieben hab, wäre es
>> katastrophal, wenn das ESP beim Bremseingriff aussteigt wegen "out of
>> memory".
> Kannst du den Qeuelltext eines ESP zeigen, damit ich bewerten kann, ob
> es überhaupt einen Vorteil von dynamischen Speicher gibt? Sonst ist es
> ein ziemlich sinnlose Argument für "dynamischer Speicher auf µC ist
> problemantisch (ohne Einschränkung)".

Na dann ist es ja gut, dass ich sowas nicht behauptet habe. Ich zitiere 
nochmal die erste Aussage, die ich in diesem Thread geschrieben habe:

Rolf M. schrieb:
> Es ist nicht grundsätzlich verboten, aber man versucht, es möglichst zu
> vermeiden. Je nach Anwendung kann es ggf. verboten sein. Und es gibt
> viele Anwendungen, wo dynamischer Speicher auch gar nicht nötig ist.

Nun versuchst du, mir zu widersprechen, indem du im Prinzip das gleiche 
sagst.

> Rolf M. schrieb:
>> Eben nicht. Man kann nicht rechtzeitig vorher reagieren, sondern erst
>> wenn die Allokation fehlschlägt.
> Und wann und wie reagiert man, wenn man nur statischen Speicher nutzt?

Wenn der alle ist, gibt es einen Linkerfehler, und man weiß, dass man zu 
wenig Speicher hat, also entweder sparen muss oder einen gößeren 
Speicher verbauen. Bei dynamischem Speicher ist es oft nicht gerade 
einfach die Situation zu erkennen und herbeizuführen, in der der 
Speicherverbrauch maximal ist, um zu ermitteln, ob ich genug Speicher 
habe.

> Oder kannst du den maximalen Speicherverbrauch garantieren?

Ja. Wenn das Programm aus dem Linker kommt, weiß ich exakt, wie viel 
statischen Speicher es braucht. Für dynamischen Speicher gilt das nicht.

: Bearbeitet durch User
von cppbert3 (Gast)


Lesenswert?

mh schrieb:
> Rolf M. schrieb:
>> Eben nicht. Man kann nicht rechtzeitig vorher reagieren, sondern erst
>> wenn die Allokation fehlschlägt.
> Und wann und wie reagiert man, wenn man nur statischen Speicher nutzt?
> Oder kannst du den maximalen Speicherverbrauch garantieren? Ich kann das
> bei meinen Programmen nicht, zumindest nicht ohne den Speicher massiv
> überdimensionieren zu müssen.

Rolf spricht von einer klaren Situation mit Anforderungen im embedded 
Bereich - sehr sehr wenig Speicher, wenig Bewegung, Interrupt-Performanz 
- also ein kleinst System oder hart Echtzeit-Anforderung

du mischt gerade normale Applikationen, Embedded mit genug Ressourcen 
und ganz kleine Embedded Systeme - einigt euch auf ein Thema sonst ist 
das total sinnlos hier

das eine 4k uC viel stärkere Probleme mit Fragmentierung als eine 16GB 
System hat - bei gleicher Software - ist hoffe ich allen hier klar

von Hans W. (Firma: Dipl.-Ing. Johann Maximilian W) (hans-)


Lesenswert?

mh schrieb:
> Rolf M. schrieb:
>> Eben nicht. Man kann nicht rechtzeitig vorher reagieren, sondern erst
>> wenn die Allokation fehlschlägt.
> Und wann und wie reagiert man, wenn man nur statischen Speicher nutzt?
> Oder kannst du den maximalen Speicherverbrauch garantieren? Ich kann das
> bei meinen Programmen nicht, zumindest nicht ohne den Speicher massiv
> überdimensionieren zu müssen.

Nur interessehalber... was machst du dann mit dem Stack?
Der ist ja auch dynamisch.

Hast du schonmal alle möglichen Verzweigungen überprüft, um den 
worst-case Stackverbrauch zu ermitteln?

Spätestens auf einer Architektur, auf der sich Interrupts unterbrechen 
können, ist das mindestens ein so großes Problem wie Speicher 
Fragmentierung.

73

von cppbert3 (Gast)


Lesenswert?

Hans W. schrieb:
> Hast du schonmal alle möglichen Verzweigungen überprüft, um den
> worst-case Stackverbrauch zu ermitteln?
>
> Spätestens auf einer Architektur, auf der sich Interrupts unterbrechen
> können, ist das mindestens ein so großes Problem wie Speicher
> Fragmentierung.

Fragmentierung wächst an

Stack kann nur eine maximale Tiefe haben - wenn keine Rekursionen 
vorhanden

schon ein Unterschied

von A. S. (achs)


Lesenswert?

cppbert3 schrieb:
> Stack kann nur eine maximale Tiefe haben - wenn keine Rekursionen
> vorhanden
> schon ein Unterschied

Das ist richtig, prüft auch ein gutes Tool, doch ist Rekursion oder auch 
nur der größte Pfad bei funktionsptr. kaum zu messen. Es reicht ja, wann 
a b aufruft usf. bis z und z dann b aufruft.

von cppbert3 (Gast)


Lesenswert?

A. S. schrieb:
> cppbert3 schrieb:
>> Stack kann nur eine maximale Tiefe haben - wenn keine Rekursionen
>> vorhanden
>> schon ein Unterschied
>
> Das ist richtig, prüft auch ein gutes Tool, doch ist Rekursion oder auch
> nur der größte Pfad bei funktionsptr. kaum zu messen. Es reicht ja, wann
> a b aufruft usf. bis z und z dann b aufruft.

Wenn man solchen Einschränkungen unterliegt sind es auch nicht mehr so 
viele Varianten in den Aufrufen - sonst könnte man das ja gar nicht 
prüfen

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.