Hallo miteinander. Ich habe ein auf Strukturen basierendes Menü aufgebaut. Ich habe nun das Problem eines immensen Stack-Bedarfs des Compilers (arbeite mit CV-AVR, dürfte aber nicht stören). Frage Eins: Warum eigentlich (kenne mich mit Compilerbau nicht aus)? Kann ich das umgehen? Frage Zwei: Da ich quasi identische Menüs mit lediglich verschiedenen Ausgabevariablen erstellt habe, liegt es nahe, lediglich einen Menübaum je Problem zu deklarieren, nur den Zeiger auf die Variable zu ändern und nur den gerade benötigten Baum zu laden. Dazu müsste ich deklarierte Strukturen aus dem Speicher entfernen, nachdem ich das Menü nicht mehr brauche. Geht das?
Immenser Stackbedarf? Das kann daran liegen, daß Du Deine Strukturen als lokale Variablen anlegst, die landen auf dem Stack. Struktur löschen? Geht so:
1 | struct bla |
2 | {
|
3 | int suelz; |
4 | char laber; |
5 | } fusel; |
6 | |
7 | memset(&fusel, 0, sizeof (struct bla)); |
8 | |
9 | // oder
|
10 | |
11 | memset(&fusel, 0, sizeof (fusel)); |
Struktur aus dem Speicher entfernen? Bei lokalen/automatischen Variablen: Einfach den Gültigkeitsbereich verlassen, das war's dann. Andernfalls solltest Du Dir mal dynamische Speicherverwaltung ansehen:
1 | struct bla *pfusel; |
2 | |
3 | pfusel = malloc(sizeof (struct bla)); |
4 | |
5 | if (!pfusel) |
6 | {
|
7 | // Fehlerbehandlung
|
8 | }
|
9 | else
|
10 | {
|
11 | pfusel->suelz = 3; |
12 | |
13 | free(pfusel); |
14 | }
|
Danke für die Antwort. Die Strukturen werden (zwingend) in der Main Funktion deklariert. In Möglichkeit Eins wird der Speicher gelöscht, aber nicht freigegeben, oder? Möglichkeit Zwei sieht vielversprechend aus. Bewirkt, wenn ich das richtig verstehe, dass die Struktur statt im Stack im Heap gespeichert wird und durch free komplett aus diesem entfernt wird. Richtig?
"Die Strukturen werden (zwingend) in der Main Funktion deklariert." Damit landen sie auf dem Stack. Das ließe sich durch Deklarieren als "static" vermeiden. Wieso eigentlich "zwingend"? "In Möglichkeit Eins wird der Speicher gelöscht, aber nicht freigegeben, oder? " Richtig erkannt. "(...) Bewirkt (...) dass die Struktur statt im Stack im Heap gespeichert wird und durch free komplett aus diesem entfernt wird. " Auch richtig erkannt. Bedenke aber bei dynamischer Speicherverwaltung die potentiellen Probleme der Speicherfragmentierung.
Die Main Funktion fragt zyklisch die Tastenbelegung ab, der ADC-Interrupt ruft alle Funktionen auf (Auswertung des Wandler-Ergebnisses, Aktualisierung des aktuellen Menüs usw.) Da der Zeiger auf das aktuelle Menü global ist, bleibt er nach der Rückkehr aus der Interrupt-Routine erhalten. Da ich in die Main zurückkehre, bleibt auch der Menübaum erhalten. Deswegen zwingend. Ich werde aber erstmal versuchen, eine dynamische Speicherverwaltung zu implementieren. Mal sehen, ob man das dann anders realisieren kann. Ich dank dir für die Hilfe!
Zeig doch mal ein bischen Code. Deine ganze Beschreibung des Problems lässt darauf schliessen, dass du da irgendwas versaust. dynamische Speicherverwaltung wird dir auch nicht helfen. Wie auch: Die Menüs müssen irgendwo gespeichert werden. Ob jetzt auf dem Stack oder im Heap (dynamische Speicherverw.) ist doch völlig Wurscht. Deswegen wird der Speicherverbrauch auch nicht kleiner, nur weil du Dinge vom Stack in den Heap verschiebst. Ganz im Gegenteil: Am Stack hat sich der Compiler schon um die Speicherverwaltung gekümmert. Im Heap muss das aber dein Pgm machen. Dazu braucht es Code und was viel wichtiger ist: Es ist Verwaltungsinformation notwendig. Die muss natürlich auch irgendwo gespeichert werden. Also: Mit einem Umstieg auf den Heap senkst du den gesamten Speicherverbrauch nicht, sondern du erhöhst ihn nur.
Das gesamte Menü im RAM zu speichern ist nicht möglich. Die Idee ist, das Menü zu zerteilen. Das Hauptmenü wird geladen. Ruft man ein Untermenü auf, wird zunächst das Hauptmenü aus dem RAM gelöscht. Dann wird nur das ausgewählte Untermenü geladen. Umgekehrt analog. Die gesamte Menüstruktur ist selbstverständlich im Flash hinterlegt. Der oben angesprochene Zwang, alles im Hauptmenü zu auszuführen, ist beseitigt. Das Konzept entwickle ich gerade. Ich werde ein Code-Beispiel vorbereiten und hochladen. Wie gravierend ist die Speicherfragmentierung einzuschätzen? Wenn das Menü nicht genutzt wird, kann ich doch den gesamten Heap freigeben und damit defragmentieren, oder?
Warum lässt Du die Menüs nicht dort, wo sie sowieso schon gespeichert sind (im ROM)? Warum müssen Menüs "geladen" werden?
> Warum lässt Du die Menüs nicht dort,
Das frag ich mich allerdings auch. Ich denke mal der Löwenanteil
der Menüs werden wohl Texte sein. Und die sind nun wirklich trivial
im Flash-ROM zu halten.
> Wenn das Menü nicht genutzt wird, kann ich doch den gesamten Heap > freigeben und damit defragmentieren, oder? Ja, wenn du zwischenzeitlich alles freigibst, hast du nie Sorgen mit der Speicherfragmentierung. Du hast auch keine Sorgen mit Speicherfragmentierung, wenn du immer nur gleich große Blöcke allozierst und (in wahlloser Reihenfolge) wieder freigibst, weil dann jeden neue Belegung den Platz eines alten Blocks wieder neu benutzen kann.
So, ich habe die Menüverwaltung komplett dynamisch verwaltet. Es wird immer nur das aktuelle Menü in den Heap geladen. Beim Menüwechsel wird der Speicher freigegeben und anschließend neu genutzt. Alle Menüs haben die gleiche Speichergröße, also ist Fragmentierung kein Problem. Redundante Menüstrukturen sind nur einmal im Speicher abgelegt (in diesem Fall vier identische Menüs zum Einstellen der Zeiten). Über die Pointer-Zuweisung findet die Auswahl des zu ändernden Wertes statt. Somit ist die Menügröße nur noch durch die Größe des Flash-Speichers begrenzt, nicht mehr durch den RAM. Ziel ist jetzt die Erweiterung um andere Teilmenüs, z.B. die direkte Ausgangssteuerung, eine Temperaturregelung u.s.w, um einen kleinen Kompaktregler zu entwerfen.
Du hast allerdings immer noch nicht erwähnt, warum du die Menüs überhaupt erst ins RAM kopierst, statt sie direkt aus dem Flash zu benutzen.
Eigentlich schon: "Redundante Menüstrukturen sind nur einmal im Speicher abgelegt (in diesem Fall vier identische Menüs zum Einstellen der Zeiten). Über die Pointer-Zuweisung findet die Auswahl des zu ändernden Wertes statt." Heißt soviel wie: Ich definiere einen Pointer auf die Time-Struktur, die angezeigt werden soll und einen auf den Wert, der in der Struktur verändert werden soll. Dann initialisiere ich die Menüstruktur. Die Alternative wäre, alle Menü-Strukturen im Flash zu initialisieren. Dann sind aber keine Änderungen an den Pointern wie oben beschrieben mehr möglich ( Error: unmodifiable value). Und das bedeutet, ich habe jede Menge redundanten Code. (Stell dir vor, meine Zeitschaltuhr soll z.B. 24 Schaltzeiten erlauben. Dann müsste ich 24 * 3 = 72 Menü-Strukuteren speichern. So muss ich nur die load_Menu Funktion um einige Case Anweisungen erweitern.) Oder hinkt da mein Denkansatz?
> Oder hinkt da mein Denkansatz?
Der hinkt sogar ganz gewaltig.
Wenn deine Benutzerführung durchsichtig und logisch
aufgebaut ist, dann lässt du den Benutzer auswählen
welche Schaltzeit er verändern möchte (Nr von 1 bis 24)
und ihn dann die Schaltzeit selbst eingeben. Wozu du da
72 Menüs brauchst ist mir rätselhaft.
Deine Menüprogrammierung ist, vorsichtig formuliert,
ziemlich grauslich. Das hängt auch damit zusammen, dass
du Benutzerführung und davon ausgelöste Aktionen nicht
sauber voneinander trennst.
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.