s(n)printf führt zum HW-Fault

Gast #4621286
Lesenswert?

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
Gast #4621343
Lesenswert?

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.
#4621987
Lesenswert?

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.
Gast #4621998
Lesenswert?

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?
Gast #4622683
Lesenswert?

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).
#4622692
Lesenswert?

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?
Gast #4623614
Lesenswert?

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.
Gast #4623626
Lesenswert?

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.
Moderator Persönliche Seite #4625343
Lesenswert?

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.
Gast #4634554
Lesenswert?

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.
Gast #4635686
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren