Hallo,
ich verwende einen ATMega168 mit einem C-Projekt (Atmel Studio 6).
In meinem Quellcode verwende ich eine Variable
1
staticvolatileuint8_t*buf=NULL;
Diese wird zuerst mit
1
buf=malloc(35);
auf einen Speicherbereich mit 35 Byte Größe festgelegt, und anschließend
mit
1
free((void*)buf);
wieder freigegeben. Der Zeiger muss volatil sein, da einzelne Werte in
einem Interrupthandler verwendet werden. Das Casten im free-Aufruf
verhindert einen Compilerfehler.
Beim nächsten malloc() Aufruf
1
wdt_enable(WDTO_250MS);
2
buf=malloc(4);
3
wdt_disable();
blockiert jedoch der malloc() Aufruf scheinbar, auch wenn der Parameter
viel kleiner ist, und die 35 Byte ja wieder freigegeben sein müssten.
Beim Blockieren mittels DebugWire bleibt die Ausführung auf der malloc()
Zeile stehen. Durch Hinzufügen der Watchdog Parameter zeigt sich, dass
der Aufruf auch ohne Debugging blockiert, denn der uC führt einen Reset
durch.
Habt ihr eine Idee was das Problem sein kann?
Danke im Voraus!
Peter Reither schrieb:> Habt ihr eine Idee was das Problem sein kann?
Die dynamische Speicherverwaltung.
Wenn du den Speicher zur Verfügung hast, kannst du ihn i.A. auch dauern
belegen. Das freie Ram kannst du nirgends verkaufen. Wozu also der
Zirkus mit dynamischer Verwaltung.
>> [...] Der Zeiger muss volatil sein, da einzelne Werte in> einem Interrupthandler verwendet werden.
Nicht der Zeiger muß volatile sein, sondern das Objekt, auf das er
zeigt; Deine Definition ist dafür schon richtig. Solltest Du aber auch
den Pointer im Interrupt ändern, müßte die Definition lauten:
1
staticvolatileuint8_t*volatilebuf=NULL;
Das hat zwar nichts mit Deinem unmittelbaren Problem zu tun, ist aber
ggf. trotzdem wichtig...
So long,
Tillomar
Tillomar Sondermann schrieb:> Das hat zwar nichts mit Deinem unmittelbaren Problem zu tun, ist aber> ggf. trotzdem wichtig...
Sehr guter Hinweis, danke!
Werner M. schrieb:> Die dynamische Speicherverwaltung.> Wenn du den Speicher zur Verfügung hast, kannst du ihn i.A. auch dauern> belegen. Das freie Ram kannst du nirgends verkaufen. Wozu also der> Zirkus mit dynamischer Verwaltung.
Du hast vollkommen recht, und ich habe auch einige Teile umgestellt. Nur
an einer Stelle ist die Alternative sehr aufwändig: Ich möchte
Menüstrukturen übertragen, die feste Datenbreiten (Typ, Index, ...) aber
auch Dynamische (Strings) enthalten. Wenn ich nun jedem Menüeintrag
einen festen Maximalwert für Strings zuweise, verschenke ich viel Platz,
da die Gesamtzahl an möglichen Zeichen beschränkt wird. Ist ein Eintrag
also kürzer als das Minimum kann der Platz von keinem anderen Eintrag
genutzt werden. Die Verwendung eines "Stringpools" hingegen ist
aufwändig, aber mir bleibt wohl keine andere Wahl, oder habt ihr eine
alternative Idee?
Dumme Frage: AVR-LibC kennt kein Garbage Collection. Wie verhinderst du
die Fragmentierung des Heap? Nach genügend malloc() für kleine Portionen
hast du nichts mehr frei für was Großes.
Georg G. schrieb:> Wie verhinderst du> die Fragmentierung des Heap?
Vielleicht etwas naiv gedacht von mir, aber da dies die einzige Stelle
ist, an der ich eine dynamische Speicherallokierung verwende, und keine
Teile, sondern immer alle verwendeten Strukturen auf einmal freigebe,
können eigentlich keine "Lücken" und somit keine Fragmentierung
entstehen.
Peter Reither schrieb:> Nur an einer Stelle ist die Alternative sehr aufwändig: Ich möchte> Menüstrukturen übertragen, die feste Datenbreiten (Typ, Index, ...) aber> auch Dynamische (Strings) enthalten. Wenn ich nun jedem Menüeintrag> einen festen Maximalwert für Strings zuweise, verschenke ich viel Platz,> da die Gesamtzahl an möglichen Zeichen beschränkt wird.
Ich werde aus Deiner Beschreibung nicht ganz schlau -- was meinst Du mit
übertragen? Stammen die Daten von außerhalb Deines Systems, und daher
weist Du nicht, wie lang die einzelnen Strings sind?
Sollten die Strings allerdings in Deinem eigenen Flash stehen -- warum
verwendest Du nicht einfach eine Liste von Zeigern? Dann spielt der
Längenunterschied schon mal keine Rolle mehr...
Gruß,
Tillomar
Peter Reither schrieb:> Georg G. schrieb:>> Wie verhinderst du die Fragmentierung des Heap?>> Vielleicht etwas naiv gedacht von mir, aber da dies die einzige Stelle> ist, an der ich eine dynamische Speicherallokierung verwende, und keine> Teile, sondern immer alle verwendeten Strukturen auf einmal freigebe,> können eigentlich keine "Lücken" und somit keine Fragmentierung> entstehen.
Ich kenne mich mit AVR-Libs nicht so aus -- aber wenn dort keine Garbage
Collection implementiert ist, dann fehlt vielleicht auch die
Zusammenfassung hintereinander liegender Blocks? Ist ja eigentlich Teil
der Garbage Collection... und dann wirst Du Dich sehr schwer tun, diesen
Speicher innerhalb des Programmes jemals wieder sinnvoll zu verwenden...
Gruß,
Tillomar
Tillomar Sondermann schrieb:> Ich kenne mich mit AVR-Libs nicht so aus -- aber wenn dort keine Garbage> Collection implementiert ist, dann fehlt vielleicht auch die> Zusammenfassung hintereinander liegender Blocks? Ist ja eigentlich Teil> der Garbage Collection...
Nö, das ist eigentlich Teil der free()-Implementierung und natürlich
auch bei der AVR-Libc vorhanden.
Wenn nur an einer Stelle wahlweise verschiedene Objekte benoetigt werden
kann man sich den dynamischen Speicher auch sparen, indem man einfach
eine Union castet.