Hallo zusammen, ich habe nun schon mehrmals gelesen, dass man auf dynamische Speicherveraltung bei Steuergeräten eher verzichtet. Begründet wurde dies meistens mit der Fragmentierung des Speichers und das man damit kein deterministisches Verhalten mehr hat. Verstehen kann ich das allerdings nicht so ganz. Kann mir das vielleicht mal einer näher erläutern oder gibt es generell Gründe dafür oder dagegen. Danke! Gruß Mike
Die zwei einfachen Gründe sind dass man einen Algorithmus braucht, der den Speicher vergibt (was nicht ganz trivial ist) und dass man bei CPUs ohne MMU tatsächlich Probleme mit der Fragmentierung bekommt.
Was weißt du denn über die Funktionsweise von malloc? Wie oft willst du es einsetzen?
Mike schrieb: > Verstehen kann ich das allerdings nicht so ganz. Wenn der Speicher fragmentiert ist, sagen wir mal, in 32Byte Blöckchen, getrennt durch vergebene Blöckchen, und du versuchst 128Byte zu reservieren... Was passiert dann? Richtig, er nimmt sichs am oberen Ende. Und da kommt ihm der Stack entgegen. Heap <-> Stack Kollisionen drohen. Nein, das möchte ich in keinem Steuergerät sehen! Schon gar nicht beim Airbus, der gerade zu den Malediven fliegt. Und auch nicht bei einem ABS System, während einer Vollbremsung.
Die Fragmentierung entsteht so: Stell Dir vor du hast insgesamt 50 Bytes RAM frei und belegst 10 mal 2 Bytes, und dann 1 mal 10 Bytes: AABBCCDDEEFFGGHHIIJJKKKKKKKKKK Und dann gibst du jeden zweiten Block frei: AA..CC..EE..GG..II..KKKKKKKKKK Danach hast du einen fragmentierten Speicher. Du hast zwar insgesamt noch 10 Bytes frei, kannst aber höchstens 2 Bytes am Stück belegen. Ob solche Lücken entstehen, und ob diese Lücken zu klein sind, hängt natürlich sehr vom jeweiligen Programm ab. Fragmentierung ist daher nicht zwangsläufig ein Problem. Vor vielen Jahren hatte ich dieses Problem auf meinem Windows 98 Rechner beobachtet. Größere Programme liessen sich irgendwann nicht mehr starten, dann musste man rebooten und es ging wieder. Ich vermute, dass Microsoft inzwischen eine clevere Lösung dagegen gefunden hat. Bei dieser Veranschaulichung habe ich vernachlässigt, a) dass die Speicherverwaltung selbst auch Speicher benötigt und b) dass der Heap je nach Systemarchitektur mit dem Stack kollidieren kann und c) Speicher meisst in größeren Blöcken vergeben wird Genaue Details dazu kannst du in der Doku der jeweiligen C Library nachlesen.
U. F. schrieb: > Wenn der Speicher fragmentiert ist, sagen wir mal, in 32Byte Blöckchen, > getrennt durch vergebene Blöckchen, und du versuchst 128Byte zu > reservieren... > Was passiert dann? > Richtig, er nimmt sichs am oberen Ende. > Und da kommt ihm der Stack entgegen. > > Heap <-> Stack Kollisionen drohen. Das verstehe ich natürlich. Vielleicht muss ich meine Frage etwas anders formulieren. Angenommen ich habe ein Programm, dass 10 mal calloc aufruft und ich bin mir sicher, dass es keine Kollision zwischen Heap und Stack geben kann. Das Programm ruft bei jedem Start exakt 10 mal calloc auf und immer in der gleichen Init Funktion. Ich weiss also zur Compilezeit, dass genau 10 Instanzen angelegt werden. Gibts hier Gründe für dynamische Speicherverwaltung?
Wenn du schon vor der Laufzeit weisst, wie viel Speicher das Programm brauchen wird, dann belege ihn besser statisch. Denn dann kann der Compiler das auch prüfen und "unerklärliche" Fehler sind bei künftigen Änderungen ausgeschlossen.
Moin, Mike schrieb: > Gibts hier Gründe > für dynamische Speicherverwaltung? Ich wuesste keine Gruende fuer gewaltsamen calloc() Einsatz, nichtmal bei "ausgebetteten" Systemen, wenn von vorneherein feststeht, wie gross der Platzbedarf an Speicher wird. Gruss WK
Der Sinn von malloc() und calloc() ist ja gerade, dass man sie verwendet wenn man NICHT vorher weiß wieviel Speicher zur Laufzeit benötigt werden wird. Bei einem Webshop weißt Du zum Beispiel vorher nicht, wie viele und welche Artikel der Kunde in seinen Warenkorb legen wird. Bei einem Steuergerät für Automotive, Luft- und Raumfahrt etc. weiß man in aller Regel vorher, wieviel Speicher man wofür braucht.
Wenn man verschiedene speicherintensive Aufgaben hat, die aber nie zugleich ausgeführt werden, dann kann man das statt über malloc auch mit einem entsprechend groß dimensionierten Stack lösen. Der fragmentiert dann nicht. Muß man nur drauf achten, daß der Compiler die entsprechenden Funktionen nicht inlined. Gerade bei GCC sollte man das mit entsprechenden Funktionsattributen erzwingen. Im Übrigen halte ich es ohnehin für Wahnsinn, den Heap auf den Stack zuwachsen zu lassen. Oder den Stack auf den Heap, bzw. bei Abwesenheit des Heaps auf die globalen Variablen. Den Heap legt man nach ganz oben, den Stack nach ganz unten (bei descending stack). Wenn man einen Stack Overflow kriegt, dann hat man kein undefiniertes Systemverhalten, das womöglich zunächst einmal gar nicht auffällt, sondern einen klaren Absturz. Wenigstens weiß man dann, daß da irgendwo ein Bug ist.
Mike schrieb: > ich habe nun schon mehrmals gelesen, dass man auf dynamische > Speicherveraltung bei Steuergeräten eher verzichtet. Begründet wurde > dies meistens mit der Fragmentierung des Speichers und das man damit > kein deterministisches Verhalten mehr hat. > Verstehen kann ich das allerdings nicht so ganz. Kann mir das vielleicht > mal einer näher erläutern oder gibt es generell Gründe dafür oder > dagegen. Die Fragmentierung ist das eine, aber bei einem Steuergerät dürfen in der Regel Teile der Funktion nicht einfach temporär mal nicht tun, nur weil grad der Speicher voll ist. Es muss für den Worst-Case für alle Situationen genug Speicher da sein. Dann kann man aber auch gleich alles statisch allokieren und braucht gar keinen dynamischen Speicher. Nop schrieb: > Im Übrigen halte ich es ohnehin für Wahnsinn, den Heap auf den Stack > zuwachsen zu lassen. Den Heap legt man nach ganz oben, den Stack nach > ganz unten (bei descending stack). Wenn man einen Stack > Overflow kriegt, dann hat man kein undefiniertes Systemverhalten, das > womöglich zunächst einmal gar nicht auffällt, sondern einen klaren > Absturz. Wenigstens weiß man dann, daß da irgendwo ein Bug ist. Was ist denn bei einem µC ein "klarer Absturz"? Je nach Prozessor gibt's evtl. auch einfach einen Wrap-around, und der Stack läuft vom Speicherende runter weiter. Oder auf z.B. einem AVR läuft er zuerst in die I/O-Register, dann in die ALU-Register rein. Gibt bestimmt auch lustige Effekte.
Rolf M. schrieb: > Was ist denn bei einem µC ein "klarer Absturz"? Dasselbe wie bei jedem anderen Prozessor auch: eine fault exception. Auf Cortex-M beispielsweise hat man einen hard fault, wenn man unterhalb des RAMs reinschreibt. Dann gehts in den exception handler, um erstens den Fehler zu signalisieren und zweitens zu rebooten. Immer noch besser, als mit einem undefinierten Zustand weiterzulaufen. Wobei der handler für einen stack overflow nicht ganz trivial ist, das geht nur in Assembler. > Je nach Prozessor gibt's > evtl. auch einfach einen Wrap-around, und der Stack läuft vom > Speicherende runter weiter. Kann natürlich auch sein. Wenn der Prozessor sowas halt nicht unterstützt, dann hilft nur noch das Erstellen eines call trees, der die benötigte Stackgröße ausgibt. Was zumindest dann geht, wenn man keine Rekursion verwendet. Den Stackbedarf der ISRs muß man natürlich auch noch draufschlagen. > Oder auf z.B. einem AVR läuft er zuerst in > die I/O-Register, dann in die ALU-Register rein. Ja, das zusammen damit, daß der Stack dann auch noch nach unten wächst, finde ich das kein besonders glückliches Hardwaredesign. Allerdings, wenn man z.B. nur 512 Bytes an SRAM hat, dann werden das ohnehin nur sehr kleine Anwendungen sein, die man dann auch von Hand noch analysieren kann. Ich ziehe halt MCUs vor, bei denen ich da ein klares Fehlerverhalten kriegen kann. Zumal der Compiler einem auch noch dazwischenhauen kann, wenn der bei Optimierung auf Größe mit GCSE arbeitet und man dann abenteuerliche Verschachtelungen kriegen kann.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.