Hallo zusammen,
bin hier etwas am Rästeln und ich hoffe ihr könnt mir Tipps zur
Fehlersuche geben.
Bei Verwendung von der Funktion s(n)printf (snprintf(str,64,"%f",d);)
springt mein STM32L1xx-Controller in den HW Fault. Aber nur an einer
Stelle des Codes bzw. der Programmausfühung. Stelle ich zum Beispiel
gleich zu Beginn in der Main() die Randbedingungen nach wird die
s(n)printf-Funktion richtig ausgeführt.
Zielspeicher ist vorhanden
Näher kann ich das Fehlerbild leider nicht beschreiben ... Sehe ja
nicht, was passiert.
Was für Randbedingungen können denn Vorliegen, dass die
s(n)printf-Funtkion abstürzt? Stack/Heap/... !?
Danke & Grüße
Jo
Jo schrieb:> Näher kann ich das Fehlerbild leider nicht beschreiben ...
...deshalb wäre etwas mehr Quelltext hilfreich
Jo schrieb:> Sehe ja> nicht, was passiert.
Debugger? ...oder einfach mal d vor dem snprintf irgendwo ausgeben...
else str=(char*)cJSON_malloc(2); /* special case for 0. */
10
if (str) strcpy(str,"0");
11
}
12
else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
13
{
14
if (p) str=ensure(p,21);
15
else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
16
if (str) sprintf(str,"%d",item->valueint);
17
}
18
else
19
{
20
if (p) str=ensure(p,64);
21
else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
22
if (str)
23
{
24
if (fpclassify(d) != FP_ZERO && !isnormal(d)) snprintf(str,64,"null");
25
else if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60) snprintf(str,64,"%.0f",d);
26
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) snprintf(str,64,"%e",d);
27
else snprintf(str,64,"%f",d);
28
}
29
}
30
return str;
31
}
Von Malloc zurückgelieferte Adresse liegt im Speicherbereich des Heaps.
coder schrieb:> ...oder einfach mal d vor dem snprintf irgendwo ausgeben...
d = 1.121999979019165033
Wenn ich d zur Laufzeit (DEbugger) auf "1.0" setze, ist die Bedingung
1
(fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)
wahr und es wird
1
snprintf(str,64,"%.0f",d);
mit dem gleichen Fehlercode ausgeführt.
Im Orignalcode von cJSON wird die sprintf-Funktion verwendet. Habe
snprintf versucht, um einen Überlauf auszuschließen.
Jo schrieb:> Ist... besser gesagt war... doch ein Stack-Problem!> Habe eben den Stack um 512Bytes vergrößert!> Nun geht's! :-D
Dann hast du das Problem also nicht behoben, sondern auf später
verschoben.
Mach erstmal aus dem "%f" ein "%lf", d ist ja ein double...
Eric B. schrieb:> Mach erstmal aus dem "%f" ein "%lf", d ist ja ein double...
%f erwartet einen double. float kann man an printf gar nicht übergeben,
da das bei der Übergabe automatisch nach double konvertiert wird.
Rolf Magnus schrieb:> Eric B. schrieb:>> Mach erstmal aus dem "%f" ein "%lf", d ist ja ein double...>> %f erwartet einen double. float kann man an printf gar nicht übergeben,> da das bei der Übergabe automatisch nach double konvertiert wird.
Ok, I stand corrected.
Nichtdestotrotz ist "Stack vergrössern" keine wirkliche Lösung. Das
Problem wird, wenn das Programm ein bisschen wächst, irgendwann mal
wieder zurückkommen.
Eric B. schrieb:> Nichtdestotrotz ist "Stack vergrössern" keine wirkliche Lösung. Das> Problem wird, wenn das Programm ein bisschen wächst, irgendwann mal> wieder zurückkommen.
Was schlägst du denn stattdessen vor, wenn nicht den Stack vergrößeren,
wenn er zu klein ist?
Rolf Magnus schrieb:> Was schlägst du denn stattdessen vor, wenn nicht den Stack vergrößeren,> wenn er zu klein ist?
Man kann (große) Arrays via malloc bereitstellen.
Bei structs ab und zu mal ein call by reference statt call by value.
Ich habe nichts gegen das vergrößern vom Stack, nur manchmal ist auch
dessen Größe auf ein Segment begrenzt.
Dirk B. schrieb:> Man kann (große) Arrays via malloc bereitstellen.
Und das macht es besser? Nein. Alle printf aus der newlib brauchen eh
Stack und Heap zuhauf. Ich hab Auf ein angepasstes printf umgestellt mit
eingeschränktem Funktionsumfang.
karl schrieb:> Und das macht es besser?
Ja.
Beim Backport eines Win32-Programms auf DOS hat es wunderbar geklappt.
Auch andere DOS-Programme funktionierten so.
Na dann zeig mal her, wie man den printf(s) der Newlib den Stack
wegnimmt...
Der TO hat natürlich einige Details unterschlagen, z.B. ob er ein RTOS
verwendet und einzelne Task-Stacks hat oder ob das alles im main() Stack
passiert. Bei letzterem ist es auch schon gleich egal, weil Stack und
Heap oft den selben Platz haben (solange man es nicht geschickter im
Sinne von robuster löst).
Karl schrieb:> Bei letzterem ist es auch schon gleich egal, weil Stack und> Heap oft den selben Platz haben (solange man es nicht geschickter im> Sinne von robuster löst).
Was soll man da großartig robuster machen? Wenn der Prozessor die
Möglichkeit hat, die Stackgröße zu begrenzen, kann man das natürlich
tun, aber wie sollte ein Programm sinnvoll reagieren, wenn der Stack
alle ist?
Rolf Magnus schrieb:> Was schlägst du denn stattdessen vor, wenn nicht den Stack vergrößeren,> wenn er zu klein ist?
Na ganz einfach: etwas anderes als printf und Konsorten verwenden -
etwas ohne malloc, ohne implizite Konvertierungen nach double und
anderen Kram, der alles nur aufbläht. Wir sind hier ja nicht auf dem PC,
sondern im µC. Da sollte man von sowas wie printf besser Abstand nehmen
und seine paar Ausgaben zu Fuß erledigen.
W.S.
Man kann den stack so legen dass er nicht überlaufen kann. Also nicht
ans Ende des Rams sondern an den Anfang.
Das Programm Stürzt dann sicher ab und man läuft nicht Gefahr, dass was
komisches passiert wenn zu viel stack belegt wird.
Heap ist in einer eigenen section. _sbrk verteilt nur daraus Speicher.
Viele der linkerskripte im Umlauf machen das anders... der benutzer soll
ja erstmal nicht behelligt werden.
W.S. schrieb:> Wir sind hier ja nicht auf dem PC, sondern im µC. Da sollte man von> sowas wie printf besser Abstand nehmen und seine paar Ausgaben zu Fuß> erledigen.
Wir sind aber auch nicht mehr auf dem Z8.
Man kann es sich natürlich zur Hauptaufgabe machen, zwei Dutzend
verschiedene Zahlenkonvertierungen zu schreiben, aber man kann auch
die vorhandenen einfach nehmen und in der gewonnenen Zeit dann was
sinnvolles tun.
Jörg W. schrieb:> und in der gewonnenen Zeit dann was> sinnvolles tun.
Bei dem Wetter im Biergarten versacken, ja? Nun, ist auch ne
Philosophie.
Aber sprintf auf nem µC benutzen zu wollen, ohne den nötigen Durchblick
zu haben und dann mit nem malloc-Fehler auszusteigen, ist
vergleichsweise albern. Anschließend das Gejammer hier im Forum: "doesnt
work, please advise".
Wieder mal die alte Gebetsmühle: Hätte der TO sich an der Lernbetty und
dem dortigen conv.c ein Beispiel genommen, dann hätte er trotz Verzicht
auf sprintf genug Zeit für den Biergarten gehabt und so ganz nebenbei
eine schlanke und versatile Ausgabe seines Krams gehabt, die schlichtweg
funktioniert.
Aber die Leute sind ja SOOO schlau und wissen alles besser.. bis sie in
ihrem tatsächlichen Unvermögen auf die Fresse fallen und dann hier
herumklagen. Doch offensichtlich hilft selbst das AufDieFresseFallen
nicht, einen Lernprozeß in Gang zu setzen.
Nun denn, bon voyage..
W.S.
W.S. schrieb:>> und in der gewonnenen Zeit dann was>> sinnvolles tun.>> Bei dem Wetter im Biergarten versacken, ja?
Ich sprach von „was sinnvollem“.
Aber zumindest bist du ja nach reichlich einer Woche Arbeit, die
dich der Verzicht auf sprintf() gekostet hat, wieder aufgetaucht. :-)
Jörg W. schrieb:> Ich sprach von „was sinnvollem“.
Ich glaub nicht, daß du das Absacken im Biergarten bei heißem Wetter als
nicht sinnvoll bezeichnen solltest. Ich zumindest find's OK so.
Aber wenn dich das als Dresdner stört, dann könnten wir ja auch von "im
Garten von Wackerbarth ein dezentes Schorle genießen" reden. Oder
meinetwegen auch Vicenz Richter?
W.S.
W.S. schrieb:> Aber wenn dich das als Dresdner stört, dann könnten wir ja auch von "im> Garten von Wackerbarth ein dezentes Schorle genießen" reden.
Zu weit weg, außerdem schon arg dekadent.
Dann lieber Biergarten. :)