Forum: Compiler & IDEs Structure löschen


von Jens Z. (bitman)


Lesenswert?

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?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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
}

von Jens Z. (bitman)


Lesenswert?

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?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

"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.

von Jens Z. (bitman)


Lesenswert?

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!

von Karl heinz B. (kbucheg)


Lesenswert?

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.

von Jens Z. (bitman)


Lesenswert?

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?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Warum lässt Du die Menüs nicht dort, wo sie sowieso schon gespeichert
sind (im ROM)? Warum müssen Menüs "geladen" werden?

von Karl heinz B. (kbucheg)


Lesenswert?

> 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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> 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.

von Jens Ziegler (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Jens Ziegler (Gast)


Angehängte Dateien:

Lesenswert?

Hab noch einen Zahlendreher beseitigt.

von Rolf Magnus (Gast)


Lesenswert?

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.

von Jens Ziegler (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

> 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
Noch kein Account? Hier anmelden.