Fehler bei strlen() in mspgcc ?

Gast #2157586
Lesenswert?

Halo,
ein mspgcc-Programm von mir für den MSP430F149 hatte das Problem, dass 
nach einer gewissen Laufzeit (> 1 Stunde) der Inhalt von Stringvariablen 
ungewollt überschrieben wurde.
Das passierte in der Nähe der strlen()-Funtion (die aber nicht die dann 
überschriebenen String-Variablen verwendete).
Nachdem ich die strlen()-Funktion jetzt durch eine selbst geschriebene 
Funktion ersetzt habe, tritt der Fehler nicht mehr auf.
Hat jemand ähnliche Erfahrungen gemacht ?

Hier der Code meiner eigenen Funktion :

unsigned int strlen_self(unsigned char *str, unsigned int li)
  {
    unsigned int si=0;
    while ((str[si] != 0) && (si<li)) si++;
    return si;
  }

wobei die Funktion so aufgerufen wird :

len_str = strlen_self(dummystr, sizeof(dummystr))  /*char  dummystr[50*/


BTW: Gibt es eine Möglichkeit, die maximale Länge eines per "char *str" 
übergebenen Strings auch innerhalb der Funktion mit sizeof() 
festzustellen ?
Gast #2157591
Lesenswert?

dann ist doch das Problem klar. du übeschreibst dir das letze 0 byte 
deines Strings umd damit liefert strlen zu viel zurück.

Du musst also den überschreiber finden und nicht eine neue strlen 
funktion programmieren.
Gast #2157602
Lesenswert?

Danke für den Tipp, das werde ich nochmals genauer überprüfen.

Allerdings logge ich die mit strlen() ermittelte Stringlänge über eine 
UART-Ausgabe mit und da wurden eigentlich immer plausible Werte 
angezeigt, die nicht über den maximalen Stringlängen lagen.
Gast #2157606
Lesenswert?

debugger schrieb:
> Allerdings logge ich die mit strlen() ermittelte Stringlänge über eine
> UART-Ausgabe mit und da wurden eigentlich immer plausible Werte
> angezeigt
wenn du dir den speicher überschreibst, kommt vermutlich überhaupt keine 
ausgabe mehr, weil das Programm einfach was anders machst als du 
erwartest.

Prüfe doch erstmal alle stellen wo du etwas in den string schreibst.
Gast #2157613
Lesenswert?

Peter II schrieb:
> wenn du dir den speicher überschreibst, kommt vermutlich überhaupt keine
> ausgabe mehr, weil das Programm einfach was anders machst als du
> erwartest.
Nein, das ist ja das kuriose : das Programm läuft ganz normal weiter. Es 
werden nur drei Strings überschrieben (mit Leerzeichen), in den 
Telefonnummern gespeichert sind, die über AT-Befehle für das Versenden 
von SMS verwendet werden.
Damit ist natürlich die SMS-Kommunikation unterbrochen, aber das 
Programm selbst läuft auf dem MSP430F149 trotzdem weiter (in einer 
Endlos-while-Schleife)
Gast #2157622
Lesenswert?

strlen macht genau das gleich wie du gemachst hat, nur das es nicht auf 
die maximale länge prüft.
Damit bleibt nur die Möglichkeit übrig das es kein 0 byte mehr gibt.

Zeigt doch mal den code wenn er nicht geheim ist.
Gast #2157628
Lesenswert?

Der Code besteht aus elf (11) separaten C-Files mit zusammen etlichen 
tausend Zeilen, den kan ich leider nicht einfach so herzeigen.
Aber trotzdem erst mal danke für den Hinweis, damit weiss ich jetzt 
genauer, nach was ich suchen muss.
Wenn ich das Problem gefunden habe, werde ich es hier posten.
Gast #2157632
Lesenswert?

mach doch mal ein test ein deine strlen funktion rein.
1
unsigned int strlen_self(unsigned char *str, unsigned int li)
2
  {
3
    if ( str[li-1] != 0 ) {
4
       senduart("schwerer fehler");
5
       while( true ) {};
6
    }
7
    unsigned int si=0;
8
    while ((str[si] != 0) && (si<li)) si++;
9
    return si;
10
  }
Gast #2157642
Lesenswert?

strlen_self() kennt man auch unter dem Namen strnlen() :). Aber im 
Allgemeinen sind strlen, strcpy & co. geächtete Funktionen, da diese die 
max. Länge des Strings nicht berücksichtigen daher unsicher sind. Also 
lieber strnlen, strncpy & co benutzen...
Gast #2157693
Lesenswert?

2ter Gast schrieb:
> strlen_self() kennt man auch unter dem Namen strnlen() :). Aber im
> Allgemeinen sind strlen, strcpy & co. geächtete Funktionen, da diese die
> max. Länge des Strings nicht berücksichtigen daher unsicher sind.

Bei strcpy gebe ich dir recht, weil es stillschweigend davon ausgeht, 
daß für den Zielstring genug Platz ist, aber strlen? Die Funktion gibt 
entweder den richtigen Wert zurück, oder der String ist kaputt, weil ihm 
die Nullterminierung fehlt. strnlen läuft dann zwar immerhin nicht über 
das Ende des für den String vorgesehenen Speicherplatzes hinaus, aber es 
wird trotzdem Mist zurückgeben.
Gast #2157730
Lesenswert?

Rolf Magnus schrieb:
> Bei strcpy gebe ich dir recht, weil es stillschweigend davon ausgeht,
> daß für den Zielstring genug Platz ist, aber strlen? Die Funktion gibt
> entweder den richtigen Wert zurück, oder der String ist kaputt, weil ihm
> die Nullterminierung fehlt. strnlen läuft dann zwar immerhin nicht über
> das Ende des für den String vorgesehenen Speicherplatzes hinaus, aber es
> wird trotzdem Mist zurückgeben.

IHMO nicht schön sowas so zu handhaben.

Auf dem Mikrocontroller kannst du den RAM bzw. Flash Adressbereich des 
Mikrocontrollers verlassen und landest bei den SFR. Wäre schon, blöd 
wenn diese Lese-sensitiv wären. Mag auf diesem uC nicht sein, aber gibt 
soft core uc auf FPGAs auf denen z.B. FIFOs memory mapped eingebunden 
sind. Diese können gelesen werden, in dem ein Lesezugriff ein memory 
mapped input register erfolgt....

Auf dem PC erntet man eine Zugriffsverletzung, wenn man "Pech" hat, 
passiert aber auch nichts
Gast #2161786
Lesenswert?

2ter Gast schrieb:
> IHMO nicht schön sowas so zu handhaben.
>
> Auf dem Mikrocontroller kannst du den RAM bzw. Flash Adressbereich des
> Mikrocontrollers verlassen und landest bei den SFR. Wäre schon, blöd
> wenn diese Lese-sensitiv wären. Mag auf diesem uC nicht sein, aber gibt
> soft core uc auf FPGAs auf denen z.B. FIFOs memory mapped eingebunden
> sind. Diese können gelesen werden, in dem ein Lesezugriff ein memory
> mapped input register erfolgt....

Naja, durch die Anwendung von strnlen() hat man den Fehler allerdings 
nicht behoben, sondern nur seine Auswirkungen verringert.

> Auf dem PC erntet man eine Zugriffsverletzung, wenn man "Pech" hat,
> passiert aber auch nichts

Mit strnlen() hat man immer das Pech, daß nichts passiert. Einen 
Fehler hat das Programm aber trotzdem, wenn der String nicht 
nullterminiert ist. Davon abgesehen müßte man dann durchs ganze Programm 
die Mögliichkeit durchziehen, eine maximale Stringlänge anzugeben, damit 
man überhaupt was hat, was man an strnlen() übergeben kann.
Gast #2164608
Lesenswert?

Ist es nicht besser, mögliche Fehlerquellen zu vermeiden?

Also mir ist es lieber einen Fehler abzufangen, als  darauf zu blind zu 
vertrauen, dass alles gut geht ( egal, ob ich für den PC oder für den uC 
einen Programm schreibe).

Sicher hast Du recht, dass das Programm ein Fehler hat, wenn sich der 
String mit bekannter Länge im Flash steht und plötzlich nicht mehr ins 
Array passt. Was machst du aber,  wenn Du die Länge nicht kennst? 
Einfach annehmen, dass der String schon eine gewisse Maximallänge hat?

Um fehlerfreiere Programme zu schreiben ist auch ein Stück Fleißarbeit. 
Wie weit man geht oder es braucht, muss aber jeder für sich entscheiden.
#2164939
Lesenswert?

2ter Gast schrieb:
> Ist es nicht besser, mögliche Fehlerquellen zu vermeiden?

Natürlich.

Aber du läufst gerade in ein 2-scheidiges Schwert hinein.
Wenn der Rest des Programmes stimmt, dann KANN strlen keinen Fehler 
produzieren. Und jetzt kommt die 2-te Schneide des Schwertes ins Spiel. 
Machst du zu viele Korrektur-Hacks in dein Programm hinein, so läufst du 
in das Problem hinein, dass du keine Programmfehler mehr bemerkst und 
sie korrigierst. Statt dessen sammeln sich die Fehler an bis es dann 
irgendwann einmal trotz aller Autokorrekturen ganz gewaltig kracht.

Been there - done that
Gast #2165065
Lesenswert?

Karl Heinz Buchegger schrieb:
> Machst du zu viele Korrektur-Hacks in dein Programm hinein, so läufst du
> in das Problem hinein, dass du keine Programmfehler mehr bemerkst und
> sie korrigierst. Statt dessen sammeln sich die Fehler an bis es dann
> irgendwann einmal trotz aller Autokorrekturen ganz gewaltig kracht.

Damit macht man keine Korrektur-Hacks! Das habe ich auch nicht 
geschrieben. Damit entdeckt man man Fehler und versucht diese zu 
beheben. Man gibt zum Beispiel den Zustand des Programms aus und 
analysiert, was passiert ist.
Gast #2165083
Lesenswert?

Was mich stutzig macht, ist, das er schreibt, das mit seiner eigenen 
Version von strnlen der "Fehler" nicht mehr auftritt.

Wenn durch die neue Fassung von strlen "der Fehler" nicht mehr auftritt 
dann ist die naheliegendste Hypothese die (wer hat gesagt Hypthosis non 
figo?), dass in der ursprünglichen Version der Ergebniswert dieses 
strlen in einem folgenden Schritt als Argument verwendet wurde, so das 
ein String ungewollt überschrieben wurde.
Wenn das aber stimmt, dann muss schon in einem früheren Schritt das 
Argument dieses Aufrufs von strlen ungewollt und unzulässig verändert 
worden sein so das strln etwas falsche zurückgibt, denn sonst würde die 
neue Version von strlen ja nicht den nachfolgenden Fehler verhindern.
D.h. die eigentliche Ursache ist schon vor Aufruf der strlen-Funktion 
gesetzt worden.

Die ursprüngliche Fragestellung war also irgendwie zu kurz gegriffen, 
vor allem wenn man beachtet das so eine Standard-Funktion wie strlen 
wahrscheinlich schon Millionenmal "getestet" worden ist.

Mir scheint der Beitrag von Karl Heinz irgendwie in die selbe Richtung 
zu gehen, aber die kleine Subdiskussion zwischen 2ter Gast und ihm 
verwirrt mich gerade ein wenig.

Klar was ich meine und hilft das weiter?
Gast #2165087
Lesenswert?

Das hier
>Wenn das aber stimmt, dann muss schon in einem früheren Schritt das
>Argument dieses Aufrufs von strlen ungewollt und unzulässig verändert
>worden sein so das strln etwas falsche zurückgibt, denn sonst würde die
>neue Version von strlen ja nicht den nachfolgenden Fehler verhindern.

ist nicht ganz vollständig.
Es kann ja auch sein, das der erste String nicht verändert sondern auch 
falsch eingelesen oder initialisiert worden ist. Man kennt ja den 
Quellcode nicht.
Gast #2165115
Lesenswert?

Ok, die Diskussion artet wohl etwas aus.

1) Sowohl mit strlen() als auch mit strnlen() kannst du den Fehler 
detektieren.

2) Das Problem bei strlen() ist, dass dieser über die Grenzen deines 
buffers hinausgehen kann, wenn er das Terminierungszeichen nicht findet. 
Bsp.: Also dein Stringbuffer ist 80 Zeichen lang, aber auf Grund eines 
Fehlers liest strlen() über die Grenzen des Buffers hinaus; er findet 
ein vermeintliches Terminierungszeichen erst nachdem 1027ten Zeichen 
(das macht strnlen(), richtig angewendet, eben nicht).

3) Über die "Grenzen lesen" sollte man nicht. Wie Du den gefundenen 
Fehler nun behandelst, liegt bei Dir.

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