Hallo, Führt dieser Code:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
zu einem Überlaufen des RAMs nach mehrmaligem Ausführen wenn man nur 256 bytes hat? Gruß Jonas
|
Anzeige
|
RAM überlauf nach einiger Zeit?Hallo, Führt dieser Code:
zu einem Überlaufen des RAMs nach mehrmaligem Ausführen wenn man nur 256 bytes hat? Gruß Jonas
Gast
#3276638
Ja. Gibt es ne Möglichkeit das anders zu Lösen? Ja, da du immer mehr Speicher anforderst, aber nie welchen freigibst Ja das wird außerhalb der Funktion mit free(...) gemacht. Könnte es an der Fragmentierung liegen? Die Antwort hast du schon gekriegt.
Ich sags dir noch mit begründung:
> char* line = malloc(sizeof(char) * length);
Reserviert Speicher, den musst du irgendwann freigeben.
Dieses vorgehen ist auf PCs durchaus üblich, aber auf einem
Mikrocontroller würde ich den Speicher nicht dynamisch verwalten,
sondern statisch.
Also du empfängst 16 Bytes, dann verarbeitest du die, dann wider 16
Bytes empfange etc.
Dann weisst du, du brauchst 16 Bytes, und du brauchst nie mehr, den du
sowieso nicht hast.
16 Bytes ist als Beispiel anzusehen.
mfg Andreas
Ich kann hier Andreas B. nur zustimmen. Besonders bei kleinen Controllern ist es bedeutend einfacher und effizienter, auf dynamische Arrays zu verzichten. Irgendwo vergisst du mal ein free() und schon hast du Speicherbereiche, die nicht mehr benutzt werden können. Das kann auf einem PC natürlich auch passieren, da sind die Auswirkungen aber im Allgemeinen nicht so gravierend.
Gast
#3278070
Wenn Du auf einen AVR (od. einen anderen µC) programmierst, dann findest Du z.B. in der Codesammlung genug Beispiele, wie man das löst. Du hast nur eine gewisse Größe vom Speicher zur Verfügung. Dein Code berücksichtigt das aber nicht. Iwie. ist es auch seltsam, dass Du immer nur 1 Byte zusätzlich allokierst. Verwende halt einen Ringspeicher und Interrupts, der bei Empfang eines Zeichens beschrieben wird. Ist dieser voll (Überschreitung) bzw. wurde die Null-Termierung erkannt, so wird ein Flag gesetzt. Ringspeicher http://www.mikrocontroller.net/articles/FIFO UART http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART UART + Ringspeicher Beitrag "AVR-GCC: UART mit FIFO" Ganz abgesehen davon, ob du den Speicher statisch oder dynamisch
reservierst: Der Speicherüberlauf ist garantiert, wenn aus irgendeinem
Grund (Fehler in der Gegenseite oder Übertragungsfehler) das Endebyte
('\0') nicht empfangen wird.
In 99% aller Fälle kann die empfangene Nachricht Byte für Byte, ohne
Zwischenspeicherung der gesamten Nachricht verarbeitet werden. Das
solltest du dann auch tun. Wenn das nicht geht, musst du den Lesevorgang
ab einer bestimmten Byteanzahl (die einen Fehlerfall signalisiert)
abbrechen.
Der empfangene String darf maximal 128 Bytes groß sein. Realloc fordert zuerst den neuen Speicher an, kopiert die Daten und gibt erst dann den alten frei. Wenn du also bei Zeichen 127 bist, hast du 127 Bytes belegt und dann werden zusätzlich die 128 Bytes für das letzte Zeichen reserviert. Das führt zu einem Speicherverbrauch von 255 Bytes. Und dein Program braucht anderweitig sicher auch noch Speicher und schon wird es knapp.
Gast
#3281455
std::string Wir sind nicht mehr in der Steinzeit. Modern Embedde Design schrieb: > Wir sind nicht mehr in der Steinzeit. Ja. Mach das mal auf einem µC mit 1 kiB RAM. Nur zu.
Gast
#3281695
Rufus Τ. Firefly schrieb: > Modern Embedde Design schrieb: >> Wir sind nicht mehr in der Steinzeit. > > Ja. Mach das mal auf einem µC mit 1 kiB RAM. > > Nur zu. Funktioniert hier wunderbar. :-P Hallo, um nochmal auf das Ram Problem zurückzukommen: Wenn der Microcontroller einige male etwas über Uart empfangen hat (ca 50-200) mal stürzt er ab. Dies zeigt sich darin, dass er immer an einem bestimmten Punkt sich aufhängt. Ich würde mich sehr darüber freuen wenn sich jemand mal meinen Code ansehen könnte und mir vielleicht ein paar Probleme nennen könnte. Bedanke mich schon mal im Foraus. Gruß Jonas Jonas E. schrieb: > Ich würde mich sehr darüber freuen wenn ... die Leute endlich mal kapieren würden das .rar ein denkbar unglückliches Format ist wenn man etwas einer breiten Öffentlichkeit zur Verfügung stellen möchte. Zip kann inzwischen nahezu jedes OS sogar nativ erstellen und lesen... Okay dann als *.zip... Seh ich das richtig, das du im RX interrupt blockierend liest? Damit müllst du dir im blödestem Fall den Stack voll, du sollstest wenigstens das Interrupt-Flag löschen, oder noch besser, ohne Interrupt in der Main pollen... Außerdem ist es extrem unschön das deine Funktion keinen Fehlerwert zurückliefert wenn es einen Overflow gab. Auch die Prüfung > 0 ist etwas unsinnig. Du hast ja nun gerade per interrupt mitbekommen, das wenigstens ein Zeichen vorliegt. Wie meinst du das, dass ich blockieren lese? Könntest du das im Code einmal zetieren? Das Interrupt-Flag wird doch automatisch gelöscht, wenn ich die Daten aus dem UART Register lese? Mit dem > 0 habe ich nun verbessert. Gruß Jonas Hier
rufst du doch die UART_gets Funktion auf, welche wiederum 20x
aufruft! Jonas E. schrieb: > Das Interrupt-Flag wird doch automatisch gelöscht, wenn ich die Daten > aus dem UART Register lese? Das kann sein, solltest du aber im Datenblatt des Prozessor verifizieren, trotz allem ist das sehr unschön im Interrupt irgendwelche länglichen UART Strings zu empfangen, das ginge in der Hauptschleife sehr viel einfacher und stressfreier. Im blödestem Falle wird nämlich der Interrupt sofort wieder aufgerufen, du hast der Hauptschleife aber gerade signalisiert das sie lesen kann und bretzelst die Daten im nächstem Moment wieder über... Stimm. Darüber habe ich noch gar nicht nachgedacht. Du würdest also ohne RXC Interrupt arbeiten? Gruß Jonas
Gast
#3284766
Jonas E. schrieb: > Du würdest also ohne RXC Interrupt arbeiten? Das nicht unbedingt, aber wenn dann holt man im Interrupt nur das eine Zeichen, das ihn ausgelöst hat, und wartet nicht auf weitere. Gruss Reinhard Reinhard Kern schrieb: > Das nicht unbedingt, aber wenn dann holt man im Interrupt nur das eine > Zeichen, das ihn ausgelöst hat, und wartet nicht auf weitere. Wie kann ich denn mit dieser Vorgehensweise einen String vernünftig empfangen? Hättest du einen Beispielcode, mit dem ich mein Vorgehen realisieren kann? Gruß Jonas
Gast
#3284978
Jonas E. schrieb: > Wie kann ich denn mit dieser Vorgehensweise einen String vernünftig > empfangen? Man richtet einen Empfangspuffer ein (fest) und hängt immer das neueste Zeichen hinten an, bis der String komplett ist - z.B. weil ein CR gekommen ist. Dann setzt man ein Flag fürs Hauptprogramm, dass eine neue Message vorliegt. Gruss Reinhard >Man richtet einen Empfangspuffer ein (fest) ich würde mal behaupten, man richtet ZWEI ein.. wenn man nämlich nur: >Dann setzt man ein Flag fürs Hauptprogramm, macht, hat man ja weiterhin das Problem, dass weiterhin Daten auflaufen, während das Hauptprogramm mit den "alten" Daten irgendwas macht.. PS: "PC-Programmierung" ist der falsche Forums-Bereich, oder ???
Gast
#3285847
Robert L. schrieb: > ich würde mal behaupten, man richtet ZWEI ein.. das kommt halt drauf an, ob weiter Daten kommen können, oder ob der Gegner erst mal auf Antwort wartet. Aber erst mal so einfach wie möglich, wir wollen Jonas ja nicht gleich ganz verschrecken. Gruss Reinhard Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|