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...
coder schrieb: > deshalb wäre etwas mehr Quelltext hilfreich
1 | /* Render the number nicely from the given item into a string. */ |
2 | static char *print_number(cJSON *item,printbuffer *p) |
3 | { |
4 | char *str=0; |
5 | double d=item->valuedouble; |
6 | if (d==0) |
7 | { |
8 | if (p) str=ensure(p,2); |
9 | 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.
Ist... besser gesagt war... doch ein Stack-Problem! Habe eben den Stack um 512Bytes vergrößert! Nun geht's! :-D Dennoch vielen Dank für die Hilfe!
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. :)
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.