Forum: Mikrocontroller und Digitale Elektronik strtol Problem (Ergebnis ist immer MAX_LONG)


von Roland N. (eroli)


Lesenswert?

Hallo zusammen,

ich lese gerade eine Datei aus, welche aus dreistelligen HEX-Zahlen 
getrennt durch ein Leerzeichen besteht.
Diese dreistelligen HEX-Zahlen beeinhalten IDs gewisser CAN-Botschaften 
auf welche ich reagieren möchte.

Mein Problem tritt nun auf, wenn ich versuche diesen "String" in eine 
long-Variable umzuwandeln. Dazu habe ich mich mal an einem 
minimalistischen Beispiel versucht:
(Die Kommentare symbolisieren Alternativen, welche ebenfalls nicht 
funktionierten)
1
//char temp[5] = {'0', '0', '0', '0', '\0'};
2
//char temp[] = "0000";
3
char *temp = "0000";
4
long test  = (long)strtol(temp, 0, 16);

Das Ergebnis dieser zwei Zeilen lautet für mich unverständlicherweise 
immer "2147483647".
Verwende ich stroul, ist das Ergebnis in der unsigned long Variable 
übrigens auch wieder der maximal mögliche Wert...

stdlib.h ist als erstes in der main.c eingebunden.

Ich bin so langsam ziemlich ratlos und ärgere mich, dass ich schon seit 
einigen Stunden an so einer "Kleinigkeit" hängen bleibe...

Vielen Dank abermals für eure Hilfe!

EDIT: Falls es wichtig sein sollte: Programmiert wird auf einem MSP430 
mittels MSPGCC in CCSv6

: Bearbeitet durch User
von Bitflüsterer (Gast)


Lesenswert?

Das Beispiel sieht so aus, als wenn es funktionieren sollte.
Das einzige auffällige Detail ist die Verwendung von 0 anstelle von 
NULL.
Das eine ist ein Integer, das andere ein Zeiger (der ja hier erwartet 
wird).
Allerdings meine ich, dass das nicht entscheidend ist.

Leider aber ist Dein Code unvollständig - bei Anfängern spielt manchmal 
das Gesamtprogramm eine Rolle weil sie den Effekt von anderen Statements 
falsch einschätzen. Poste bitte ein komplett kompilierbares und doch 
minimales Programm.

Leider schreibst Du auch nicht auf welche Weise genau Du feststellst, 
das MAX_LONG herauskommt - Anfänger benutzten manchmal unpassende 
Methoden um Ergebnisse zu verifizieren oder interpretieren Ergebnisse 
falsch.

Darüber hinaus - und wenn alles bisher gesagte, unzutreffend sein 
sollte, ist das am wahrscheinlichsten - gibt es die Möglichkeit, dass 
für die Benutzung von LONG eine andere Library gelinkt werden muss. 
Einen ähnlichen Fall gibt es für Floating Point Libs beim AVR. Leider 
kenne ich mich mit CCS nicht aus, aber die Dokumentation sollte das 
klären - oder ein anderer freundlicher Mitleser.

von Roland N. (eroli)


Lesenswert?

Hallo,

danke für die Antwort. Natürlich kann ich dir auch ein einfaches, 
komplettes Beispielprogramm anbieten:
1
#include "stdlib.h"
2
3
int main(void)
4
{
5
  char *temp = "000A";
6
  long test = (long)strtol(temp, NULL, 16);
7
  if (test == 0)
8
  {
9
    test++;
10
  }
11
  return 0;
12
}

Die IF-Abfrage dient dabei nur als Abgriffspunkt zum Testen des Wertes 
mittels Debugger. Die Variable test enthält danach den Wert 2147483647 
und nicht wie ich eigentlich vermuten würde den Wert 10.

EDIT: Das selbe (Fehl-?)Verhalten bekomme ich auch bei Verwendung des 
TI-Compilers...

: Bearbeitet durch User
von Helmut L. (helmi1)


Lesenswert?

#include "stdlib.h"

 int main(void)
 {
   char temp[10];
    strcpy(temp,"000A");
   long test = (long)strtol(temp, NULL, 16);
   if (test == 0)
   {
     test++;
   }
   return 0;
 }

aendere das Programm mal so ab.

von Roland N. (eroli)


Lesenswert?

Hallo!

Damit bekomme ich folgende Warnungen

implicit declaration of function 'strcpy' 
[-Wimplicit-function-declaration]incompatible implicit declaration of 
built-in function 'strcpy'  main.c

und ich kann mit dem Debugger nicht mehr in die Variable test 
reinschauen irgendwie. Vermutlich funktioniert es aber immer noch nicht, 
da in folgendem Code
1
#include "stdlib.h"
2
3
int main(void)
4
{
5
     char temp[10];
6
     strcpy(temp, "000A");
7
     long test = (long)strtol(temp, NULL, 16);
8
     if (test == 0)
9
     {
10
       test++;
11
     }
12
     if (test == 10)
13
     {
14
       test += 5;
15
     }
16
     return 0;
17
18
}

Die Anweisung test += 5 nicht ausgeführt worden ist.

Ich bin jedoch über diesen Thread 
Beitrag "Hex ASCII -> Int" auf die hexatoi von Timmo H. 
aufmerksam geworden, welche ganz gut funktioniert.

Natürlich hilft mir das nur bedingt bei meinem ursprünglichen Problem, 
aber damit kann ich jetzt erstmal weiter machen.

Wenn Ihr jedoch noch Ideen habt, warum diese Standard-Funktion nicht wie 
gewünscht funktioniert, dann lasst es mich wissen ;-)

von Helmut L. (helmi1)


Lesenswert?

Roland M. schrieb:
> implicit declaration of function 'strcpy'
> [-Wimplicit-function-declaration]incompatible implicit declaration of
> built-in function 'strcpy'  main.c

Dann solltes du

#include <string.h>

noch einbinden.

von Roland N. (eroli)


Lesenswert?

Gesagt, getan, aber der Wert von Test ist immer noch 2147483647...

von Helmut L. (helmi1)


Lesenswert?

dann aendere das in strcpy(temp,"0x000A") ab.

von Dirk B. (dirkb2)


Lesenswert?

Wie stellst du fest, dass temp diesen Wert hat?

von Roland N. (eroli)


Lesenswert?

Also auch so
1
#include "stdlib.h"
2
#include "string.h"
3
4
int main(void)
5
{
6
     char temp[10];
7
     strcpy(temp, "0x000A");
8
     long test = (long)strtol(temp, NULL, 16);
9
     if (test == 0)
10
     {
11
       test++;
12
     }
13
     if (test == 10)
14
     {
15
       test += 5;
16
     }
17
     return 0;
18
19
}

tritt der Fehler immer noch auf. Es dürfte nicht an strcpy liegen, da 
der Wert in der Variable temp korrekt ist. Das habe ich, genau wie auch 
den Wert von test, mittels Debugger (JTAG) überprüft.

von Dirk B. (dirkb2)


Lesenswert?

Sind die Optimierungen ausgeschaltet?

von Karl H. (kbuchegg)


Lesenswert?

Nimm da auf jeden Fall mal den Cast raus
1
     long test = (long)strtol(temp, NULL, 16);

Du brauchst ihn nicht. Der Cast kann dir aber eine ev. Fehlermeldung vom 
Compiler verhindern.
Man verwendet nie leichtfertig irgendwelche Casts! Casts sind Waffen und 
man setzt sie nur ein, wenn es nicht anders geht. Aber auf keinen Fall 
inflationär, in dem man alles niedercastet.

von Karl H. (kbuchegg)


Lesenswert?

Du kannst im Debugger reinschauen? Gut

Was ist, wenn du das machst
1
...
2
     char temp[10];
3
     strcpy(temp, "0x000A");
4
     char* endptr;
5
6
     long test = strtol(temp, &endptr, 16);
7
8
...

welchen Wert hast du dann in endptr und wie ist die Speicheradresse von 
temp?

von Karl H. (kbuchegg)


Lesenswert?

Was ich auch mal probieren würde:
kommt strtol damit zurecht, wenn du zur Basis 10 konvertieren lässt?
1
...
2
     char temp[10];
3
     strcpy(temp, "10");
4
     long test = (long)strtol(temp, NULL, 10);
5
...
es geht nur darum, ob strtol dann mit dem richtigen Wert daher kommt. 
Ev. ist das strtol abgespeckt und kann nicht mit anderen Basen arbeiten.

von temp (Gast)


Lesenswert?

Roland M. schrieb:
> tritt der Fehler immer noch auf. Es dürfte nicht an strcpy liegen, da
> der Wert in der Variable temp korrekt ist. Das habe ich, genau wie auch
> den Wert von test, mittels Debugger (JTAG) überprüft.

Variablen auf dem Stack sind für den Debugger manchmal ein Problem.
Nicht benutzte oder sinnlos erscheinende Variablen fliegen da gern mal 
raus.
Teste das mal so:
1
volatile long test=0;
2
int main(void)
3
{
4
  test = strtol("000A", NULL, 16);

Das volatile ist zwar überflüssig, trotzdem weiß keiner wie der Compiler 
optimiert. Unter Windows bzw. LPC1769 und gcc geht alles riichtig. Kann 
ja sein, dass die Implementierung von strtol bei dir keine hex-Werte 
kann.

von Roland N. (eroli)


Lesenswert?

Also zur Basis 10 beträgt der Wert von test "1073692671". Dasselbe 
passiert bei einer Konvertierung zur Basis 10 OHNE Cast.

Bei der endptr-Modifikation liegt temp an der Adresse 0x005BF0 und hat 
den Value 0x005BF0 (stimmt das wirklich? Wenn ich mir den Wert Anzeigen 
lassen, dann sehe ich "9x999A.U.M" und das macht ja Sinn).

endptr zeigt nach dem strtol-Aufruf auf die Adresse 0x5BF1, das ist das 
x! Ist ja auch logisch, da ein x bei einer Konvertierung zur Basis 10 
ziemlich sinnfrei ist.

Wenn ich die Basis nun wieder zu 16 ändere, dann zeigt endptr auf die 
Adresse 0x5BF6 (das ist ein . (Punkte sind übrigens nicht anzeigbare 
Zeichen wie z.B. 0x00 und Andere)). Auffällig ist für mich, dass die 
Variable temp nach dem Aufruf aus den Werten "0x0......." besteht...?

EDIT: Auch mit einer globalen, volatilen Variable test besteht das 
Problem weiterhin. Hierbei habe ich nochmal auf die Variable temp nach 
Aufruf geachtet und diesmal war sie unangetastet, also "0x000A". 
Vielleicht habe ich davor mit einen falschen Klick im Debugger den Wert 
manipuliert (das passiert schonmal recht schnell leider). endptr zeigte 
hierbei auf einen freien Bereich von temp ("also auf einen punkt").

EDIT2: Optimierungen sind komplett ausgeschaltet.

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Um sicherzustellen, daß Dein Debugger Dich nicht anlügt:

Konvertiere den erhaltenen Wert in einen String, und lass Dir den (als 
Hexdump des Speichers) vom Debugger anzeigen, da hat der Debugger es 
beim Lügen etwas schwieriger.

von Bitflüsterer (Gast)


Lesenswert?

Nun ja.

Der cast auf long ist, wie schon geschrieben, unnötig und unter 
Umständen sogar kontraproduktiv.

In eine analoge Kategerie fallen auch die Versuche mit globalen oder 
volatile Variablen. Der Code sollte auch ohne das funktionieren. 
Allenfalls würde das, überraschende, funktionieren dieser Varianten auf 
Fehler im Compiler hinweisen und das wäre recht unwahrscheinlich (wenn 
auch nicht unmöglich). Und der Versuch von dem Benutzer temp zeigt, dass 
der Code mit anderen Compilern und anderen CPUs funktioniert.

Ich nehme gewisse Unsicherheiten bei der Ablesung von Variablenwerten 
wahr, die hier möglicherweise eine Rolle spielen. Allerdings habe ich 
nicht den Eindruck, dass die hier entscheidend sind.

Ich würde an Deiner Stelle, Roland, zunächst einmal gründlich die 
Dokumentation des Compilers bzw. der Libraries studieren und 
insbesondere die Dokumentation zu Deiner Version von strtol. Lies bitte 
nicht eine allgemeine Dokumentation im Internet oder sonstwo. Stelle 
bitte sicher, dass Du definitiv die Dokumentation Deines Compilers und 
Deiner Library liest. Es ist sehr wahrscheinlich, dass Du Die schon auf 
Deiner Festplatte hast; dass sie bei der Installation des Compilers 
mitinstalliert worden ist.

Die Zielrichtung dieser Lektüre ist die Klarstellung ob Deine Variante 
von strtol oder ob sie nicht alle Basen unterstützt.

Ein Detail ist fällt mir allerdings noch ein: Probiere doch mal bitte, 
ob ein String wie "0" (also nicht "0000") auch nicht korrekt umgewandelt 
wird.

von Roland N. (eroli)


Lesenswert?

Hallo zusammen!

@Bitflüsterer:
Auch dieses Programm:
1
#include "stdlib.h"
2
#include "string.h"
3
4
volatile long test = 0;
5
6
int main(void)
7
{
8
     char temp[10];
9
     strcpy(temp, "0");
10
     char *endptr;
11
     test = strtol(temp, &endptr, 10);
12
     if (test == 0)
13
     {
14
       test++;
15
     }
16
     if (test == 10)
17
     {
18
        test += 5;
19
     }
20
     return 0;
21
}
funktioniert leider nicht. Das Ergebnis ist wieder falsch (1073692671). 
Der endptr zeigt auf die zweite Stelle in temp - also auf das ende des 
strings. Dasselbe gilt für den Aufruf zur Basis 16.

@Alle:
Wie gesagt habe ich schon auf eine andere Funktion zurückgegriffen, 
weshalb die Priorität dieses Problems ein wenig gesunken ist für mich. 
Dennoch frage ich mich natürlich auch, warum das diese Funktion nicht 
funktioniert. Ich denke schon, dass ich sehr wohl in der Lage bin 
mittels des Debuggers gewisse Werte aus Variablen auslesen zu können, 
daher glaubt mir bitte, wenn ich schreibe welche Variable welchen Wert 
hat.

Vielleicht schaue ich mir mal die Dokumentation meines benutzten 
Compilers an, aber auch da sehe ich eher schwarz. Zum Einen habe ich 
zwei Compiler getestet (MSPGCC und den von TI) und bei beiden kam es zu 
Problemen. Zum Anderen glaube ich, dass ein solches Dokument recht 
schwer verdauliche Kost für mich sein dürfte...

EDIT: Beim MSPGCC bin ich auf Folgendes Dokument gestoßen, welches mir 
den Eindruck vermittelt, dass die Funktion in vollem Umfang zur 
Verfügung stehen muss (sonst würde wohl kaum auf die Standard-C-Doku 
verwiesen würden): http://mspgcc.sourceforge.net/manual/x1109.html

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Roland M. schrieb:
> Ich denke schon, dass ich sehr wohl in der Lage bin mittels des
> Debuggers gewisse Werte aus Variablen auslesen zu können, daher glaubt
> mir bitte, wenn ich schreibe welche Variable welchen Wert hat.

Selig sind die, die ihren Werkzeugen blind Vertrauen schenken.

Zum eigentlichen Problem: Der Quelltext der Funktion sollte bei den 
Runtime-Library-Sourcen dabei sein, den kannst Du Dir ja mal zu Gemüte 
führen.

von Roland N. (eroli)


Angehängte Dateien:

Lesenswert?

In \ti\gcc\msp430-elf\include\stdlib.h steht zumindest
1
long  _EXFUN(strtol,(const char *__restrict __n, char **__restrict __end_PTR, int __base));

In \ti\ccsv6\tools\compiler\msp430_4.3.4\lib\mklib.c ist ebenfalls ein 
Aufruf von strtol zu verzeichnen.

Außerdem finde ich die folgende Datei in 
\ti\ccsv6\tools\compiler\msp430_4.3.4\lib\src\strtol.c, welche ich euch 
mal hochlade mit diesem Post.

Ich denke mal die angehängte Datei ist entscheidend und zumindest für 
mich sieht es nach einer vollständigen Implementierung aus...

: Bearbeitet durch User
von Bitflüsterer (Gast)


Lesenswert?

> Ich denke mal die angehängte Datei ist entscheidend und
> zumindest für mich sieht es nach einer vollständigen
> Implementierung aus...

Das lässt sich ja einfach feststellen. Und auch die Frage, ob das 
tatsächlich der Code der Funktion ist, die ausgeführt wird.

Füge diese Funktionsdefinition in ein Testprogramm ein und steppe sie 
durch. Dann siehst Du ja was geschieht.
Benenne die Funktion am bestem um, um jeden Zweifel zu beseitigen.

Evtl. musst Du das _CODE_ACCESS-Attribut entfernen - das kann ich nicht 
beurteilen.

von Bitflüsterer (Gast)


Lesenswert?

>  Zum Einen habe ich zwei Compiler getestet (MSPGCC und den
> von TI) und bei beiden kam es zu Problemen.

Bei beiden Compilern das identische Problem? Das halte ich für sehr 
unwahrscheinlich. Das liegt an was anderem.

von Jürgen S. (jurs)


Lesenswert?

Roland M. schrieb:
> Vielleicht schaue ich mir mal die Dokumentation meines benutzten
> Compilers an, aber auch da sehe ich eher schwarz. Zum Einen habe ich
> zwei Compiler getestet (MSPGCC und den von TI) und bei beiden kam es zu
> Problemen. Zum Anderen glaube ich, dass ein solches Dokument recht
> schwer verdauliche Kost für mich sein dürfte...

Da Du als Rückgabewert LONG_MAX bekommst, tritt bei der Umwandlung 
offenbar ein Range-Error auf.

Was passiert denn mit Deinem Compiler, wenn Du mal <errno.h> mit in 
Deinen Code einbindest und die Variable "errno" auf 0 setzt, bevor Du 
strtol aufrufst?

Einer kleiner Arduino-Code für ein Testprogramm mit Errorhandling für 
die strtol Funktion wäre sowas wie:
1
#include <errno.h>
2
#include <limits.h>
3
void setup() {
4
  Serial.begin(9600);
5
  char *n = "0CA000AB";
6
    char *p;
7
    long test;
8
    errno = 0;
9
    test = strtol(n, &p, 16);
10
11
    if (p == n)
12
        Serial.println("No digits found.\n");
13
    else if ((test == LONG_MIN || test == LONG_MAX) && errno == ERANGE)
14
        Serial.println("Value out of range.\n");
15
    else
16
    {
17
        Serial.print("Value is ");
18
        Serial.println(test);
19
    }
20
}
21
22
void loop() {}

Vielleicht kannst Du dieses strtol()-Errorhandling ja mal auf Deinen 
Compiler umsetzen.

von Roland N. (eroli)


Lesenswert?

Doch, gerade nochmal getestet.

GNU v4.9.1 und TI v4.3.4

Um die Funktion aus der Datei in mein Programm einzubauen und mir die 
Unterfunktionsaufrufe rauszusuchen, habe ich im Moment keine Zeit für. 
Ich denke aber, dass du Recht hast, und der Fehler irgendwo anders 
liegt. Ich frage mich nur wo das sein könnte, dann an meinem kleinem 
Testprogramm ist ja nicht viel Spielraum um etwas falsch machen zu 
können...

@Jürgen S.:
Nach diesem Umbau lande ich im Else-Case (wo eigentlich alles in Ordnung 
sein sollte), aber meine test-Variable hat wieder einen falschen Wert 
(1073692671).

Den Wert von errno kann ich euch leider nicht mitteilen, da der Debugger 
hier sagt: cannot load from non-primitive location

: Bearbeitet durch User
von Daniel V. (danvet)


Lesenswert?

Roland M. schrieb:
> Doch, gerade nochmal getestet.
>
> GNU v4.9.1 und TI v4.3.4
>
> Um die Funktion aus der Datei in mein Programm einzubauen und mir die
> Unterfunktionsaufrufe rauszusuchen, habe ich im Moment keine Zeit für.
> Ich denke aber, dass du Recht hast, und der Fehler irgendwo anders
> liegt. Ich frage mich nur wo das sein könnte, dann an meinem kleinem
> Testprogramm ist ja nicht viel Spielraum um etwas falsch machen zu
> können...

Ich tippe auch auf den Debugger bzw. Optimierung.
Es scheint nicht klar zu sein, wo der Wert von "test" zu finden ist.
Manchmal hilft hier den Disassembler zu verwenden und die einzelnen 
Assemblerbefehle durch zu steppen. Dann bist du dir sicher, wo der 
Rückgabewert von srttol() hingeschrieben wird (wenn überhaupt).

von Daniel V. (danvet)


Lesenswert?

Roland M. schrieb:

> @Jürgen S.:
> Nach diesem Umbau lande ich im Else-Case (wo eigentlich alles in Ordnung
> sein sollte), aber meine test-Variable hat wieder einen falschen Wert
> (1073692671).
>

Im Else-Case ist "test" schon wieder ungültig und eventuell 
überschrieben.
Setze den Breakpoint auf das erste "if" und schau was in "test" steht.

von Helmut L. (helmi1)


Lesenswert?

Roland M. schrieb:
> Den Wert von errno kann ich euch leider nicht mitteilen, da der Debugger
> hier sagt: cannot load from non-primitive location

Einfach auf eine andere Variable kopieren.


Hast du das ganze auch mal im Simulator getestet anstatt im JTag 
debugger?

von Bitflüsterer (Gast)


Lesenswert?

> ... die Unterfunktionsaufrufe rauszusuchen, ...

Zu welchem Zweck würdest Du das tun wollen?

> Ich frage mich nur wo das sein könnte, dann an meinem
> kleinem Testprogramm ist ja nicht viel Spielraum um
> etwas falsch machen zu können...

Das ist im wesentlichen beantwortet worden:
1. Bedienungsfehler des Debuggers
2. Bedienungsfehler des Compilers.

Mehr können wir mangels tieferer Informationen und wegen Deines 
Ausschlusses von Punkt 1. nicht sagen.

Das der Compiler schuld ist, d.h. dass zwei unterschiedliche Compiler 
das selbe Fehlverhalten zeigen ohne das der Programmierer dafür 
verantwortlich ist, ist ungefähr so wahrscheinlich wie ein Lotto-Gewinn.

von Roland N. (eroli)


Lesenswert?

Nochmals Hallo!

errno hat direkt nach dem Aufruf einen Wert von "0".
test hat direkt nach dem Aufruf einen Wert von "1073692671".

Siehe folgendes Programm:
1
#include "stdlib.h"
2
#include "string.h"
3
#include "errno.h"
4
5
volatile long test = 0;
6
7
#define LONG_MAX  2147483647
8
#define LONG_MIN  -2147483648
9
10
int main(void)
11
{
12
     char temp[10];
13
     strcpy(temp, "0");
14
     char *endptr;
15
     errno = 0;
16
     test = strtol(temp, &endptr, 10);
17
     int kopie2 = errno;
18
     long kopie3 = test;
19
     if (temp == endptr)
20
     {
21
       test++;
22
     }
23
(X)     else if ((test == LONG_MIN || test == LONG_MAX) && errno == ERANGE)
24
     {
25
       test++;
26
     }
27
     else
28
     {
29
       test++;
30
     }
31
     return 0;
32
33
}

Was mir dabei jedoch ins Auge gefallen ist, ist die folgende Warnung für 
die mit (X) markierte Zeile:
this decimal constant is unsigned only in ISO C90  main.c


Ich weiß nicht, wie es zu einem Bedienungsfehler kommen sollte? Ich 
benutze dieselbe IDE mit denselben Einstellungen und derselben Hardware, 
welche ich auch für mein richtiges Projekt OHNE Probleme einsetze.

: Bearbeitet durch User
von Helmut L. (helmi1)


Lesenswert?

Roland M. schrieb:
> #define LONG_MAX  2147483647
> #define LONG_MIN  -2147483648

Schreib das mal so:

#define LONG_MAX  2147483647L
#define LONG_MIN  -2147483648L

von Daniel V. (danvet)


Lesenswert?

Roland M. schrieb:
> Nochmals Hallo!
>
> errno hat direkt nach dem Aufruf einen Wert von "0".
> test hat direkt nach dem Aufruf einen Wert von "1073692671".

"direkt nach dem Aufruf" ?
Wo sitzt der Breakpoint?
Wieso ist "test" nicht 0 (direkt nach dem Aufruf) ???

von Bitflüsterer (Gast)


Lesenswert?

> this decimal constant is unsigned only in ISO C90  main.c

Ersetze
1
#define LONG_MAX  2147483647
2
#define LONG_MIN  -2147483648

durch
1
#include <limits.h>

Wozu noch eine eigene Präprozessor-Definition?

> Ich weiß nicht, wie es zu einem Bedienungsfehler kommen sollte?
Ja eben. Ich behaupte ja nicht, dass Du es weißt, sondern das Du es 
nicht weißt.

> Ich benutze dieselbe IDE mit denselben Einstellungen und
> derselben Hardware, welche ich auch für mein richtiges
> Projekt OHNE Probleme einsetze

Moment mal. In Deinem RICHTIGEN Projekt tritt das Problem nicht auf?
Das hatte ich anders verstanden.

von Roland N. (eroli)


Lesenswert?

Der Breakpoint sitzt auf dem Funktionsaufruf von strtol (7 Zeilen über 
der mit (X) markierten Zeile). Danach mache ich drei Prozedurschritte 
mit dem Debugger. Mit dem ersten Schritt wird strtol ausgeführt. Mit dem 
zweiten wird errno ausgelesen (0). Mit dem dritten wird test in kopie3 
gesichert mit dem Wert von 1073692671.

> Wieso ist "test" nicht 0 (direkt nach dem Aufruf) ???

Wieso sollte es?

> #define LONG_MAX  2147483647L
> #define LONG_MIN  -2147483648L

Auch dies bringt nichts, die Warnung bleibt bestehen.

EDIT:

> Moment mal. In Deinem RICHTIGEN Projekt tritt das Problem nicht auf?
> Das hatte ich anders verstanden.

Doch, da trat das Problem auch auf. Daher bin ich auf (s.o.) hexatoi 
umgestiegen, welches ohne Probleme läuft. Da das strtol auch in meinem 
kleinem Testprogramm nicht funktioniert, mache ich mir kenie Sorgen, 
dass in meinem richtigen Projekt irgendetwas schief läuft...

EDIT2:
Das Inkludieren von limits.h hat die Warnung beseitigt.

: Bearbeitet durch User
von Detlev T. (detlevt)


Lesenswert?

Hallo,

bei mir (Atmel Studio 6.2) funktioniert alles. Wenn ich im folgenden auf 
die while Schleife einen Breakpoint setze, gibt der Debugger dort für 
die Variable test eine 10 zurück.
1
#include "stdlib.h"
2
#include <avr/io.h>
3
4
int main(void)
5
{
6
  char *temp = "000A";
7
  long test = (long)strtol(temp, NULL, 16);
8
  if (test == 0)
9
  {
10
    test++;
11
  }
12
  
13
  while(10 == test) PORTB ^= 0x01;
14
  
15
  return 0;
16
}
Ohne die while-Schleife optimiert der Compiler (Einstellung -Os) 
hingegen die Variable test quasi weg. "Quasi" heißt, dass zwar die 
Funktion strtol aufgerufen wird, deren Ergebnis aber nirgendwo mehr 
abgelegt wird. Wozu auch - Wird ja im folgenden nicht mehr gebraucht. 
Das ändert sich hier durch die while-Schleife.

Die oben genannte Vermutung des fahrlässigen Gebrauchs des Debuggers ist 
also offensichtlich zutreffend.

von Bitflüsterer (Gast)


Lesenswert?

> Da das strtol auch in meinem kleinem Testprogramm nicht
> funktioniert, mache ich mir kenie Sorgen,
> dass in meinem richtigen Projekt irgendetwas schief läuft...

Daraus, daß ein Problem in zwei verschiedenen Programmen auftritt und 
nicht nur in einem von beiden, schliesst Du daraus das Du in dem einen 
von den beiden keinen Fehler machst?

Das ist hübsch. :-) Nur logisch ist es nicht.

von Daniel V. (danvet)


Lesenswert?

Detlev T. schrieb:
> Ohne die while-Schleife optimiert der Compiler (Einstellung -Os)
> hingegen die Variable test quasi weg. "Quasi" heißt, dass zwar die
> Funktion strtol aufgerufen wird, deren Ergebnis aber nirgendwo mehr
> abgelegt wird. Wozu auch - Wird ja im folgenden nicht mehr gebraucht.
> Das ändert sich hier durch die while-Schleife.
>
> Die oben genannte Vermutung des fahrlässigen Gebrauchs des Debuggers ist
> also offensichtlich zutreffend.

Thanx!

von Roland N. (eroli)


Lesenswert?

Bitflüsterer schrieb:
>> Da das strtol auch in meinem kleinem Testprogramm nicht
>> funktioniert, mache ich mir kenie Sorgen,
>> dass in meinem richtigen Projekt irgendetwas schief läuft...
>
> Daraus, daß ein Problem in zwei verschiedenen Programmen auftritt und
> nicht nur in einem von beiden, schliesst Du daraus das Du in dem einen
> von den beiden keinen Fehler machst?
>
> Das ist hübsch. :-) Nur logisch ist es nicht.

Zumindest kann ich damit ausschließen dass irgendein Laufzeitfehler 
auftritt, der den Aufruf dieser Funktion stört. Natürlich ist das kein 
Beleg für die Fehlerfreiheit des restlichen Projekts ;-)

> Ohne die while-Schleife optimiert der Compiler (Einstellung -Os)
> hingegen die Variable test quasi weg. "Quasi" heißt, dass zwar die
> Funktion strtol aufgerufen wird, deren Ergebnis aber nirgendwo mehr
> abgelegt wird. Wozu auch - Wird ja im folgenden nicht mehr gebraucht.
> Das ändert sich hier durch die while-Schleife.

Erstens sind alle meine Optimierungen ausgeschaltet (und ich meine 
wirklich alle). Zweitens habe ich dazu die IF-Anweisungen eingefügt. Es 
kann also wirklich nicht am Optimierer liegen (diesmal - ich hatte 
schonmal ein ähnliches Problem).

> Die oben genannte Vermutung des fahrlässigen Gebrauchs des Debuggers ist
> also offensichtlich zutreffend.
Das sehe ich leider anders. Nur weil ihr den Fehler genau so wenig 
finden könnt wie ich, heißt das doch nicht, dass ich auf einmal keinen 
Debugger mehr bedienen kann?

Ich kann gerne eine while-Schleife für dich dahinter setzen, aber das 
wird das Ergebnis nicht ändern. Soll ich es dennoch für dich versuchen?

von Daniel V. (danvet)


Lesenswert?

Roland M. schrieb:
> Ich kann gerne eine while-Schleife für dich dahinter setzen, aber das
> wird das Ergebnis nicht ändern. Soll ich es dennoch für dich versuchen?

Das Ergebnis würde mich interessieren...

von Dirk B. (dirkb2)


Lesenswert?

Roland M. schrieb:
> Zweitens habe ich dazu die IF-Anweisungen eingefügt

Alles was in und nach dem IF passiert hat keine Auswirkung nach Aussen 
und kann daher weggelassen werden.

test wird in deinem Programm überhaupt nicht gebraucht.

von Roland N. (eroli)


Lesenswert?

Dirk B. schrieb:
> Roland M. schrieb:
>> Zweitens habe ich dazu die IF-Anweisungen eingefügt
>
> Alles was in und nach dem IF passiert hat keine Auswirkung nach Aussen
> und kann daher weggelassen werden.
>
> test wird in deinem Programm überhaupt nicht gebraucht.

Das ändert immer noch nichts daran, dass die Optimierungen ausgeschaltet 
sind. Und zwar alle.

Folgender Aufbau für Dich, Daniel V. (danvet):
1
#include <msp430.h>
2
#include "stdlib.h"
3
#include "string.h"
4
#include "errno.h"
5
#include "limits.h"
6
7
volatile long test = 0;
8
9
int main(void)
10
{
11
     char temp[10];
12
     strcpy(temp, "0");
13
     char *endptr;
14
     errno = 0;
15
     test = strtol(temp, &endptr, 10);
16
     int kopie2 = errno;
17
     long kopie3 = test;
18
     if (temp == endptr)
19
     {
20
       test++;
21
     }
22
     else if ((test == LONG_MIN || test == LONG_MAX) && errno == ERANGE)
23
     {
24
       test++;
25
     }
26
     else
27
     {
28
       test++;
29
     }
30
31
     while(test == 0)
32
     {
33
       P10OUT ^= BIT7;
34
     }
35
     while(test != 0)
36
     {
37
       P10OUT ^= BIT6;
38
     }
39
40
     return 0;
41
42
}

Gleiches Verhalten. Falscher Wert in test. Erste While-Schleife wird 
nicht angegangen. Die zweite logischerweise schon.

Gibt es noch weitere Ideen?

: Bearbeitet durch User
von Daniel V. (danvet)


Lesenswert?

Roland M. schrieb:

> Gibt es noch weitere Ideen?
Ja, kannst du bitte das hier:

>
1
>      if (temp == endptr)
2
>      {
3
>        test++;
4
>      }
5
>      else if ((test == LONG_MIN || test == LONG_MAX) && errno == ERANGE)
6
>      {
7
>        test++;
8
>      }
9
>      else
10
>      {
11
>        test++;
12
>      }
13
> 
14
>

mal weglassen.
Was passiert dann.

von Detlev T. (detlevt)


Lesenswert?

Hallo nocheinmal,

mit ausgeschalteter Optimierung (-O0) und Breakpoint auf dem return gibt 
mein Debugger für test als Ergebnis eine 10 im folgenden Programm. Bei 
Veränderung von temp ändert sich dieser Wert entsprechend.
1
#include "stdlib.h"
2
3
int main(void)
4
{
5
  char *temp = "000A";
6
7
  long test = (long)strtol(temp, NULL, 16);
8
  if (test == 0)
9
  {
10
    test++;
11
  }
12
    
13
  return 0;
14
}
Roland M. schrieb:
> Erstens sind alle meine Optimierungen ausgeschaltet (und ich meine
> wirklich alle).
Das bezweifle ich nach meinem Test aber doch sehr.

von Roland N. (eroli)


Angehängte Dateien:

Lesenswert?

Daniel V. schrieb:
> Roland M. schrieb:
>
>> Gibt es noch weitere Ideen?
> Ja, kannst du bitte das hier:
>
> SchnippSchnapp
>
> mal weglassen.
> Was passiert dann.

Dasselbe. Sofort nach dem Aufruf von strtol, wechselt der Wert von test 
von 0 auf 1073692671. Danach geht es in die zweite while-Schleife.

>> Erstens sind alle meine Optimierungen ausgeschaltet (und ich meine
>> wirklich alle).
>Das bezweifle ich nach meinem Test aber doch sehr.

Hierzu hänge ich Dir gerne noch einen kleinen Beweisscreenshot an...

: Bearbeitet durch User
von Daniel V. (danvet)


Lesenswert?

Roland M. schrieb:
> Dasselbe. Sofort nach dem Aufruf von strtol, wechselt der Wert von test
> von 0 auf 1073692671. Danach geht es in die zweite while-Schleife.

Na dann belassen wir es dabei, dass dein strtol() kaputt ist.

von Roland N. (eroli)


Lesenswert?

Klingt komisch... Aber wenn es sonst keine weiteren Ideen mehr gibt, 
dann muss ich das wohl so hinnehmen...

Jedenfalls liegt es ganz sicher nicht an einer Optimierung.

Da der Compiler wohl kaum fehlerhaft sein wird, muss es wohl an mir 
liegen. Allerdings könnt weder Ihr noch Ich mir sagen, was ich wohl 
falsch mache...

von Karl H. (kbuchegg)


Lesenswert?

Daniel V. schrieb:
> Roland M. schrieb:
>> Dasselbe. Sofort nach dem Aufruf von strtol, wechselt der Wert von test
>> von 0 auf 1073692671. Danach geht es in die zweite while-Schleife.
>
> Na dann belassen wir es dabei, dass dein strtol() kaputt ist.

Ist aber trotzdem unbefriedigend. strtol hat zwar ein paar 
Kleinigkeiten, die berücksichtigt werden wollen, aber die 
Grundimplementierung ist eigentlich so einfach (und vor allen Dingen ist 
sie ja seit Jahrzehnten bekannt), dass die Wahrscheinlichkeit dafür 
recht gering ist.

Allerdings: Ich kann auch keine Erklärung anbieten. Ich denke jetzt wäre 
der Zeitpunkt erreicht, an dem nur noch der Gang runter zum 
Assemblercode bleibt um nachzusehen, wie das Ergebnis zustande kommt.

von Roland N. (eroli)


Lesenswert?

Morgen vielleicht... Für heute habe ich die Nase doch recht voll.

Ich wollte euch hiermit nichts vorwerfen. Ich habe durchweg gute 
Erfahrungen mit diesem Forum hier und den Menschen, die sich hier 
rumtreiben und anderen helfen, gesammelt. Sei es die Reaktionszeit, die 
Fachlichkeit oder der Humor. Aber irgendwie kommen wir hier dennoch 
nicht weiter...

von Detlev T. (detlevt)


Lesenswert?

Roland M. schrieb:
> Hierzu hänge ich Dir gerne noch einen kleinen Beweisscreenshot an..

Ich kenne diese IDE nicht. Was steht denn in der Auswahlbox für die 
Optimierung, wenn sie nicht leer ist? Wenn die IDE das so für den 
Compiler umsetzt:

-O<Inhalt Auswahlbox>

Dann entspricht diese Einstellung nämlich dem Optimierungslevel 1. Also 
hier vielleicht explizit einmal ein 0 eintragen.

von Roland N. (eroli)


Lesenswert?

None -O0
Optimize -O1
Optimize More -O2
Optimize Most -O3

Allerdings habe ich auch schon die Erfahrung gesammelt, dass die 
Checkboxen zur Optimierung selbst bei "None -O0" noch greifen und 
explizit ausgestellt werden müssen.

Ich habe es nun nochmals mit der Einstellung "None -O0" getestet. Es hat 
sich nichts verändert.

von Bitflüsterer (Gast)


Angehängte Dateien:

Lesenswert?

Eine Alternative (oder ein Schritt vor dem "Assembler-Studium") wäre 
vielleicht die oben von mir schon vorgeschlagene.
Den Quellcode von strtol nehmen und mal austesten. Ich habe mal den 
Code, wie ich ihn testen würde, angehängt. (Man braucht da keine 
Unterfunktion rauszusuchen).

Was die Optimierung betrifft, halte ich den Compileraufruf für 
maßgebend. Bei einer IDE weiß man nie, was die sich selbst denkt. Poste 
doch mal den Aufruf selbst.

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
Noch kein Account? Hier anmelden.