Hallo, ich programmiere schon seit längerem an einem größerem Programm für den atmega328p in C++. Letzeres einfach, weil ich das größere Projekt objektorientiert umsetzen wollte und templates etc. nutzen wollte ... war auch quasi ein Art test wie gut das mit C++ auf einem 8bit Microcontroller funtkioniert. (Eig. sehr gut muss ich sagen, abgesehen von fehlender OOP Integration für Interrupts). Nun kam ich plötzlich gestern an den Punkt an, dass meine Serial Library nicht mehr funktionierte, was ich als RAM Problem ausfindig gemacht habe. Da ich da wenig Ahnung habe, habe ich ein paar Experimente gemacht mit folgendem Code #include "Stream.h" int freeRam(); void useRam(); //2015 Bytes RAM, wenn useRam() Methode auskommentiert ist //1535 Bytes RAM mit useRam() Methode, aber nicht aufgerufen //1535 Bytes RAM mit useRam() Methode und 1032 Bytes RAM während dem Aufruf int main() { useRam(); avr::cout << freeRam() << '\n'; while(1); } int freeRam () { extern int __heap_start, *__brkval; int v; return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); } void useRam() { float points[][3] = {{15, 0, 0}, {7.5, 0, 0}, {15, 0, 0} , {0, 0, 0}, {0, -15, 0}, {0, -7.5, 0}, {0, -15, 0}, {0, 0, 0}, {0, 0, 15}, {0, 0, 7.5}, {0, 0, 15}, {0, 0, 0}, {0, 15, 15}, {0, 0, 0}, {0, -15, 15}, {0, 0, 0}, {0, -15, -15}, {0, 0, 0}, {0, 15, -15}, {0, 0, 0}, {-15, 0, 0}, {-7.5, 0, 0}, {-15, 0, 0}, {0, 0, 0}, {0, 15, 0}, {0, 7.5, 0}, {0, 15, 0}, {0, 0, 0}, {0, 0, -15}, {0, 0, -7.5}, {0, 0, -15}, {0, 0, 0}, {0, -15, -15}, {0, 0, 0}, {0, 15, -15}, {0, 0, 0}, {0, 15, 15}, {0, 0, 0}, {0, -15, 15}, {0, 0, 0}}; for(float (&point)[3]: points) { for(float& value: point ) { avr::cout << value << '\n'; } } avr::cout << freeRam() << '\n'; } Dabei ist mir folgendes aufgefallen. Habe ich die Methode mit dem übergroßen array auskommentiert, habe ich 2015 Bytes zur Verfügung. Habe ich die Methode aber rufe sie nicht auf, habe ich nur noch 1500 Bytes zur Verfügung an RAM.Rufe ich sie auf, schrumpft der RAM während des Ausrufs nochmal auf 1000 Bytes. Deklariere ich das Array global statt lokal habe ich auch 1500 Bytes zur Verfügung, bei Aufruf der Methode etwas weniger. Letzeres kann ich sehr gut nachvollziehen. 120 float * 4 Bytes ... knapp 500 Bytes die dauerhaft belegt werden, da es global ist. Bei Aufruf der Methode wird für etwas RAM verbraucht, um sich zu merken woher man kam (soweit ich weiß). Auch bei der lokalen variante macht es Sinn, dass RAM in Höhe von 500 Bytes belegt wird während dem Aufruf und anschließend wieder freigegeben wird. Was aber keinen Sinn für mich ergibt ist, dass das lokale Array scheinbar wie das globale Array immer 500 Bytes belegt (selbst wenn die Methode nicht aufgerufen wird). Ruft man die Methode auf, werden nochmal während des Aufrufs 500 Bytes belegt. Ich habe gelesen, dass das irgendwie Architektur bedingt ist, konnte den Erklärungen aber nicht so ganz folgen. Es wäre sehr nett, wenn mir das jemand nochmal in verständlich erläutert. Außerdem die Frage, sollte dieses Verhalten korrekt sein, warum sollte ich dann lokale Variablen verwenden, wenn sie im Gegensatz zu globalen Variablen scheinbar doppelt so viel RAM belegen? (Neben dem kleinerem scope ist doch eig der Vorteil an lokalen Variablen, dass sie nur während dem Aufruf RAM belegen). Vielen Dank! Grüße Leon
Ich vermute, dass das Verhalten sehr stark von den Compiler- und Linker- Optionen abhängt, welche die Optimierung steuern.
Schau nach, wo die Initialisierungs-Werte des Arrays liegen. Vielleicht im RAM, weil flash-lesen nach Startup zu teuer ist. Es wird ja bei jedem Aufruf neu übergebügelt.
Vielen Dank für die schnellen Antworten! Ich habe den Compiler auf die Optimierungstufe Os für Speicher Optimierung eingestellt. Sollte es da andere Optimierungen geben, die einen doppelten RAM Bedarf vermeiden, wäre es sehr nett, wenn du oder andere sie mir mitteilen. Da ich Probleme mit einem zu kleinem RAM habe, liegt es natürich in meinem Interesse das zu optimieren (Für so große Arrays würde ich da den PROGMEN nutzen ... das Beispiel diente nur zum testen und verdeutlichen). @achim S. deine Antwort verstehe ich nicht so ganz. Eig möchte ich ja, sofern ich die Methode nicht aufrufe, dass das array gar nicht initalisiert wird ... wie man es doch eig. von lokalen Variablen erwartet? Dies scheint nicht der Fall zu sein ... Ich wüsste auch nicht wie ich das nachschauen kann?
Leon0402 schrieb: > Eig möchte ich ja, > sofern ich die Methode nicht aufrufe, dass das array gar nicht > initalisiert wird Warum hast du dann Initialisierungswerte hin geschrieben? Wenn du das Schlüsselwort "static" verwendet, gibt es im Speicher nur eine Instanz des Arrays und dann wird es auch nur einmal beim Programmstart (vor Ausführung der main() Funktion) initialisiert.
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.