Forum: Mikrocontroller und Digitale Elektronik AVR: malloc() Aufruf blockiert


von Peter Reither (Gast)


Lesenswert?

Hallo,

ich verwende einen ATMega168 mit einem C-Projekt (Atmel Studio 6).

In meinem Quellcode verwende ich eine Variable
1
static volatile uint8_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!

von Werner M. (Gast)


Lesenswert?

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.

von Tillomar S. (tillomar)


Lesenswert?

Peter Reither schrieb:
>
1
 static volatile uint8_t *buf = NULL;
>
> [...] 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
static volatile uint8_t * volatile buf = NULL;

Das hat zwar nichts mit Deinem unmittelbaren Problem zu tun, ist aber 
ggf. trotzdem wichtig...

So long,
Tillomar

von Peter Reither (Gast)


Lesenswert?

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?

von Georg G. (df2au)


Lesenswert?

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.

von Peter Reither (Gast)


Lesenswert?

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.

von Tillomar S. (tillomar)


Lesenswert?

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

von Tillomar S. (tillomar)


Lesenswert?

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

von Stefan E. (sternst)


Lesenswert?

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.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Außerdem sollte selbst wenn kein Speicher mehr vorhanden ist nicht 
blockiert werden...

von Purzel H. (hacky)


Lesenswert?

Wenn nur an einer Stelle wahlweise verschiedene Objekte benoetigt werden 
kann man sich den dynamischen Speicher auch sparen, indem man einfach 
eine Union castet.

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.