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 ?
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.
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.
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.
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)
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.
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.
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 | }
|
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...
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.
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
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.
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.
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
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.
Da war ich zu fix... Und es geht ja beim debugging um das FINDEN und BEHEBEN beim Debbugging. So kann ich wenigstens etwas feststellen und verhindere das "gewaltig krachen".
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?
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.
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.
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.