Ich habe habe mehrere Webseiten, die im stm32 Flash liegen. Die HTML
Daten enthalten Variablen, die ich vor der Ausgabe noch ersetzen muss.
Dazu verwende ich folgende Funktion:
Jedoch bleibt der STM32 immer wieder hängen und zwar oft reproduzierbar.
Ich vermute, dass es was mit der Speicherreservierung zu tun hat. Meine
Funktion frisst auch ordentlich Platz im RAM. Gibt es eine bessere
Methode, bei der man mit weniger Speicher auskommt? Das Problem ist,
dass die Variablennamen und die dazugehörigen Werte nicht die gleiche
Länge haben, sonst wäre es kein Problem.
Beispiel:
sprintf(cTempArr, "%2X-%2X-%2X-%2X-%2X-%2X",MAC_ADDR0, MAC_ADDR1,
MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5);
str_replace(dhtml, "$LAN:MAC$", cTempArr);
MfG
Artur schrieb:> Gibt es eine bessere> Methode, bei der man mit weniger Speicher auskommt?
warum machst du die ersetzung einzeln? Man könnte die Daten auch während
der ausgabe ersetzen, dann brauchst du überhaupt keinen RAM dafür.
Grundsätzlich kommst du natürlich am Problem, dass du mehr Speicher
allokieren musst nicht herum, solange die die generelle Strategie nicht
veränderst (zb Ersetzen erst während der Ausgabe)
Allerdings kannst du dir ja den temporär angelegten Speicher (samt
zugehöriger Länge) auch für den nächsten Aufruf aufheben und wenn die
Funktion dann drauf kommt, dass dieser Speicher ausreichen würde, musst
du keinen neuen Speicher anlegen sondern kannst den vorhandenen
recyclen.
Der Speicher Fragmentierung würde das sicherlich gut tun.
LwIP ließt die Daten sonst direkt aus dem Flash, da wüsste ich nicht,
wie ich die sonst ersetzen könnte. Mein Problem ist, dass der STM
Hardfault handler hat, komischerweise bei einem HTML File, welches nicht
größer als manch andere Files sind. Außerdem habe ich statische Sachen,
wie Header und Footer der Webseite, ich lese deshalb alle Daten erst in
RAM ein, ersetze die dynamischen Daten im HTMl file und baue vor der
Ausgabe alles mit strcat zusammen (wobei ich da auch Speicher malloc
habe).
html_file = malloc(file_header.len + strlen(dhtml) + file_footer.len);
Alles scheitern nur an der string replace Funktion, ich habe das Gefüll,
dass es nicht an der malloc Funktion liegt, sondern an der Umsetzung der
string replace Funktion, wobei mir kein besserer Weg einfällt.
Artur schrieb:> Alles scheitern nur an der string replace Funktion, ich habe das Gefüll,> dass es nicht an der malloc Funktion liegt, sondern an der Umsetzung der> string replace Funktion, wobei mir kein besserer Weg einfällt.
Ich habe eher das Gefühl, dein eigentliches Problem liegt ganz woanders
im Code. Was du siehst sind lediglich die Auswirkungen, aber nicht die
Ursache. Ein Programmfehler kann ganz woanders im Code stecken und das
System soweit 'destabilisieren', dass der Fehler sich dadurch bemerkbar
macht, dass diese Funktion nicht mehr richtig funktioniert.
Wenn ich Deine Funktion richtig verstehe, ist *string_in nach dem Aufruf
größer.
Wenn Du also nur den nötigen Speicher vor dem Aufruf reserviert hast,
kracht es natürlich.
Im allgemeinen sollte man malloc nur da benutzen, wo es nötig ist. Also
nur dann wenn die erzeugende Funktion den Speicher nicht wieder
freigibt, sondern eine andere.
Ansonsten ist es effektiver, wenn man einfach eine lokale Variable der
maximal benötigten Größe anlegt.
Peter
Peter Dannegger schrieb:> Wenn ich Deine Funktion richtig verstehe, ist *string_in nach dem Aufruf> größer.> Wenn Du also nur den nötigen Speicher vor dem Aufruf reserviert hast,> kracht es natürlich.
@Artur
Da hat er recht (und ich habs übersehen :-)
Und was wir alle bisher übersehen haben: Deine Allokierung des
temporären Strings ist um 1 Zeichen zu kurz.
Bei solchen Sachen IMMER die Länge des allokierten Speichers mitgeben,
damit die Funktion darauf achten kann, diese nicht zu überschreiten.
Unzählige Programmabstürze und Hackerangriffe gehen auf das Konto dieses
Versäumnisses und haben C den Ruf eines unhandhabbaren Monsters
eingebracht.
// erst jetzt ist sicher gestellt, dass die Operation gut gehen wird
22
23
...
24
}
Wenn du aber sowieso den Originalstring veränderst, brauchst du doch
auch den temporären String nicht:
im Original die Einfügestelle suchen
Den Teil dahinter in der benötigten Größe nach hinten verschieben und so
eine Lücke bauen.
In die Lücke den Ersatztext einsetzen.
Prüfen, ob das Original über genügend Platz verfügt, musst du aber so
und so.
>Bei solchen Sachen IMMER die Länge des allokierten Speichers mitgeben,>damit die Funktion darauf achten kann, diese nicht zu überschreiten.
Reicht es nicht, wenn ich innerhalb der Funktion die Länge abfrage?
>Strings ist um 1 Zeichen zu kurz.
Wo du Recht hast...Thx
>Wenn du aber sowieso den Originalstring veränderst, brauchst du doch>auch den temporären String nicht.
Werde am Montag probieren, es ohne den Temp-Speicher umzusetzen.
Artur schrieb:>>Bei solchen Sachen IMMER die Länge des allokierten Speichers mitgeben,>>damit die Funktion darauf achten kann, diese nicht zu überschreiten.>> Reicht es nicht, wenn ich innerhalb der Funktion die Länge abfrage?
Innerhalb der Funktion hast du nur einen Pointer auf den Speicher. Damit
kannst du nicht feststellen wie groß der Speicherbereich ist. Du
kannst feststellen, wie lang der String ist, aber das sagt ja nichts
darüber aus, wie groß das Array ist, in dem der String abgelegt wurde.
Diese Information braucht die Funktion und da sie diese nicht selbst
ermitteln kann, muss sie der Aufrufer mitgeben.
im Grunde eine Variation von
1
voidfoo(char*pMem)
2
{
3
strcpy(pMem,"Hallo World");
4
}
5
6
intmain()
7
{
8
charstr[3];
9
foo(str);
10
}
"Hallo World" passt niemals in einen char[3] rein. foo hat aber keine
Chance festzustellen, dass sich hinter pMem ein char[3] verbirgt.
So programmiert, ist das kein Problem mehr.