Forum: Mikrocontroller und Digitale Elektronik Freien Arbeitsspeicher ermitteln


von Donk (Gast)


Lesenswert?

Hi,

ich habe hier ein kleines Embedded-Board das ohne MMU oder virtuellem 
Speicher daherkommt und rein bare-metal in ANSI-C programmiert wird. Der 
zu benutzende Speicher wird in meiner Applikation zu Beginn einmalig mit 
diversen malloc()s alloziiert.

Jetzt habe ich folgendes Problem: Über das Linker-Command-File ist der 
Heap mit einer bestimmten Größe festgelegt. Wie viel Speicher durch die 
verschiedenen malloc()s geholt wird, kann ich mir ausrechnen und auf 
Basis dessen ermitteln, wie viel da tatsächlich noch übrig ist.

Aber: ich hätte gerne eine Möglichkeit, um beides zu verifizieren - ob 
meine Heap-Definition im Linkerfile und meine angenommene 
Speicherbelegung richtig ist.

Wie kann ich das (gerne auch nur in einer DEBUG-Version, die nicht 
ausgeliefert wird) am besten machen?

Gibt es eine ANSI-C-Funktion, welche mir in so einem Szenario den noch 
verfügbaren Heap ausspuckt?

Danke!

von Noch einer (Gast)


Lesenswert?

Üblicherweise laufen Stack und Heap aufeinander zu. Du vergleichst dann 
einfach die Adressen der lokalen Variablen mit den Pointern, die 
malloc() liefert.

Kannst auch eine kleine Test-Funktion schreiben, die rekursive Aufrufe 
und mallocs() macht, bis die Grenzen erreicht sind. Normalerweise 
überschreibt der Stack ohne jede Warnung den Heap.

von Falk B. (falk)


Lesenswert?

@ Donk (Gast)

>zu benutzende Speicher wird in meiner Applikation zu Beginn einmalig mit
>diversen malloc()s alloziiert.

Dann braucht man auch kein malloc sondern kann alle Speicherbereiche 
statisch als globale Variablen definieren, dann sieht man auch direkt 
wieviel Speicher beötigt wird.

von Einer K. (Gast)


Lesenswert?

Donk schrieb:
> Der
> zu benutzende Speicher wird in meiner Applikation zu Beginn einmalig mit
> diversen malloc()s alloziiert.
Kannst du darauf nicht verzichten und die Variablen fest anlegen?

von Donk (Gast)


Lesenswert?

Falk B. schrieb:
> Dann braucht man auch kein malloc sondern kann alle Speicherbereiche
> statisch als globale Variablen definieren, dann sieht man auch direkt
> wieviel Speicher beötigt wird.

Es sei denn ich habe dynamisch unterschiedliche Konfigurationen, die ich 
erst beim Booten ermitteln kann und die jeweils andere Speichergrößen 
benötigen.

von Einer K. (Gast)


Lesenswert?

Das ist bei einem fest verbautem µC eher ungewöhnlich.
Und auch dann kann man meist mit fixen Strukturen und Union arbeiten

von Donk (Gast)


Lesenswert?

U. F. schrieb:
> Und auch dann kann man meist mit fixen Strukturen und Union arbeiten

In diesem Fall geht es um Ringbuffer mit unterschiedlichen Größen und 
unterschiedlichen gepufferten Strukturen. Klar, irgendwie kann man alles 
immer irgendwie in Unions mit Arrays mit verschachtelten Strukturen mit 
eingebetteten Hühnerknochen mit gecastetem Schneckenschleim verfrickeln, 
aber das Ganze soll ja auch noch les- und wartbar bleiben.

Und da sind ein paar mallocs() ausschließlich am Programmstart meiner 
Meinung nach das weitaus kleinere Übel.

von Einer K. (Gast)


Lesenswert?

Nunja....
Dein malloc() wird irgendwo eine verkettete Liste bilden.
Diese sollte man auswerten können.

von Donk (Gast)


Lesenswert?

Noch einer schrieb:
> Kannst auch eine kleine Test-Funktion schreiben, die rekursive Aufrufe
> und mallocs() macht, bis die Grenzen erreicht sind.

Das scheint mir auch die beste Lösung zu sein - Danke!

von Stefan F. (Gast)


Lesenswert?

Ich würde auch mit malloc antesten, wie viel Speicher zu belegen kannst 
- allerdings in einer Schleife, nicht nicht rekursiv.

Fange mit der maximalen RAM Größe minus 1/8 an. Wenn das geht, gib den 
Speicher wieder frei un liefere die Größe als Testergebnis zurück. Wenn 
es nicht geklappt hat, reduziere den Wert wieder um 1/8. So tastest du 
dich schrittweise an den richtigen Wert heran, wobei die Schritte immer 
kleiner werden.

Abbruchbedingung für die Schleife: Wenn die Zahl nach dem Subtrahieren 
kleiner als 8 ist, breche den test ab und melde "RAM voll".

Bedenke, dass das freie RAM auch fragmentiert sein kann. Mit dieser 
Schleife erhälst du (ungefähr) den größten Zusammenhängenden Block. 
Darüber hinaus könnten aber auch noch kleinere Speicherblöcke verfügbar 
sein. Für eine grobe Abschätzung, ob genug RAM frei ist, reicht das 
meistens jedoch.

von Dirk B. (dirkb2)


Lesenswert?

Stefan U. schrieb:
> Fange mit der maximalen RAM Größe minus 1/8 an.

Und woher kennt man die maximale RAM Größe?
Man muss das System kennen. Dann kann man aber auch für das eigentliche 
Problem die Systemfunktionen nehmen.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Dann kannst Du Dir Dein malloc auch ganz einfach selbst schreiben, in 
dem Du einen Zeiger auf den Anfang des heaps initialisiert und mit jeder 
Allozierung um den allozierten Speicher weiter bewegst. Die Differenz 
zwischen dem Zeiger und dem Ende des Heaps ist dann der noch freie 
Speicher.

Alles andere ist nur gerate und hängt sehr stark von der Implementierung 
des Heaps ab.

von Dumdi D. (dumdidum)


Lesenswert?

Torsten R. schrieb:
> in
> dem Du einen Zeiger auf den Anfang des heaps initialisiert

wie macht man das (Code)?

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Dumdi D. schrieb:
> Torsten R. schrieb:
>> in
>> dem Du einen Zeiger auf den Anfang des heaps initialisiert
>
> wie macht man das (Code)?

in etwa so, wenn Du den heap zwischen __HEAP_START und __HEAP_END legst.
1
#include <stdlib.h>
2
3
extern char __HEAP_START;
4
extern char __HEAP_END;
5
6
static char const * heap_end = &__HEAP_END;
7
static char const * heap_top = &__HEAP_START;
8
9
void* allocate_memory( size_t s )
10
{
11
    void* result = 0;
12
13
    if ( heap_end - heap_top >= s )
14
    {
15
        result = (void*)heap_top;
16
        heap_top += s;
17
    }
18
19
    return result;
20
}

von Stefan F. (Gast)


Lesenswert?

Im Fall von AVR unf svg-gcc geht das so nicht. Denn dort beginnt der 
Heap an einem Ende des Speichers und der Stack am anderen Ende. Wenn sie 
wachsen, treffen sich Heap und Stack irgendwo in der Mitte. Beide 
Speicherbereiche haben keine feste Größe.

Siehe http://www.nongnu.org/avr-libc/user-manual/malloc.html

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Stefan U. schrieb:
> Im Fall von AVR unf svg-gcc geht das so nicht. Denn dort beginnt der
> Heap an einem Ende des Speichers und der Stack am anderen Ende. Wenn sie
> wachsen, treffen sich Heap und Stack irgendwo in der Mitte. Beide
> Speicherbereiche haben keine feste Größe.

Das ist bei sehr vielen Controllern so. Selbst wenn head und stack keine 
von Dir fest definierte Größe haben, wirst Du Dir Gedanken darüber 
machen wollen, wie groß Dein Stack sein muss.

Und nach dem Du Dir die Gedanken gemacht hast, hält Dich auch niemand 
davon ab, dem Stack eine feste Größe zu geben. Der Rest ist dann 
statischer Speicher plus Heap.

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.