Hallo zusammen,
ich konnte heute (nach etlichem Suchen einen Fehler beim Build mit dem
AVR-GCC 4.8.1/Atmel Studio 6.2 einkreisen. Und zwar war im Quelltext
eine Funktion vorhanden, die durch großzügiges Auskommentieren noch
effektiv folgenden Inhalt hatte:
1
uint_fast8_tfoo(void)
2
{
3
uint_fast8_tstatus=0;
4
5
error:
6
returnstatus;
7
}
Das Vorhandensein dieser Funktion führt zu einer Fehler
"RUNCOMPILERTASK", leider auch völlig ohne Konsolenausgabe.
Jetzt stellt sich natürlich die Frage: Was ist hier eigentlich
verbotenes passiert? Welche Regel verbietet das Label "error" an dieser
Stelle?
Viele Grüße
W.T.
Walter T. schrieb:> leider auch völlig ohne Konsolenausgabe.
sicher?
test.c: In function 'foo':
test.c:8:5: warning: label 'error' defined but not used [-Wunused-label]
error:
Ja, das ist nur eine Warnung.
Und ein Label ohne Verwendung ist kein Fehler.
Wenn der avr-gcc wirklich drüber stolpert, ist es wohl wirklich mal ein
Compilerfehler.
Ich habe es mit einem Linuc-gcc 4.8.4 probiert. Der gibt natürlich auch
die Warnung aus, aber sonst klappt es.
Peter II schrieb:> test.c:8:5: warning: label 'error' defined but not used [-Wunused-label]> error:
Diese Warnung ist selbstverständlich vorhanden. Aber der Fehler muß ja
weitaus später stattfinden.
Markus F. schrieb:> Ich würde mal das Label umbenennen. Möglicherweise ist bloss die IDE zu> blöd, die Compilerausgaben richtig zu parsen und zu interpretieren.
Tatsache! Wenn ich das label umbenenne, funktioniert der Build.
Danke für die Antwort!
So schnell vergeht der Tag, und wie schnell ist nichts gemacht :-)
Walter T. schrieb:> Tatsache! Wenn ich das label umbenenne, funktioniert der Build.
Das kommt davon, wenn die Leute IDEs bauen, die einfach nur nach
dem Wort "error" suchen.
Schreib' Atmel einen Bugreport.
Walter T. schrieb:> Tatsache! Wenn ich das label umbenenne, funktioniert der Build.
nun ja ein Label auch error zu nennen war keine gute Idee.
Ich tue mich ja auch immer schwer mit Namen, aber reservierte Namen
meide ich wie die Pest.
Joachim B. schrieb:> nun ja ein Label auch error zu nennen war keine gute Idee.
Das ist völlig üblich.
1
intsomefunc(someargs)
2
{
3
blah;
4
if(errorcondition)
5
gotoerror;
6
proceed;
7
8
return0;// success
9
10
error:
11
dosomecleanup;
12
return-1;// failure
13
}
Wenn man davon ein paar Fehlerbedingungen hat, spart das einfach
ein immer tiefer schachtelndes (und dadürch völlig unübersichtlich
werdendes) if/else-Gerippe.
> Ich tue mich ja auch immer schwer mit Namen, aber reservierte Namen> meide ich wie die Pest.
Wenn es ein reservierter Name ist, kann man ihn nicht benutzen,
aber "error" ist halt keiner.
Jörg W. schrieb:> Joachim B. schrieb:>> Ich tue mich ja auch immer schwer mit Namen, aber reservierte Namen>> meide ich wie die Pest.>> Wenn es ein reservierter Name ist, kann man ihn nicht benutzen,> aber "error" ist halt keiner.
das sah der gcc oder Atmel wohl anders, aber lass uns darüber nicht
streiten
Joachim B. schrieb:> das sah der gcc oder Atmel wohl anders, aber lass uns darüber nicht> streiten
Das ist kein reservierter Name, das ist ein Programmierfehler in der
IDE.
Jörg W. schrieb:> Das ist völlig üblich.> int somefunc(someargs)> {> blah;> if (error condition)> goto error;> proceed;>> return 0; // success>> error:> do some cleanup;> return -1; // failure> }>> Wenn man davon ein paar Fehlerbedingungen hat, spart das einfach> ein immer tiefer schachtelndes (und dadürch völlig unübersichtlich> werdendes) if/else-Gerippe.
Hm? Dafür braucht man doch keine Verschachtelung?
1
intsomefunc(someargs)
2
{
3
interror=0;
4
5
// every called function returns 0 on OK, or a non-0 error code
Markus F. schrieb:> Das ist kein reservierter Name, das ist ein Programmierfehler in der> IDE.
ist das nicht piepegal wenns nicht funzt?
was geht schneller?
Labelnamen ändern oder auf Bugbeseitigung hoffen?
Eric B. schrieb:> Dafür braucht man doch keine Verschachtelung?
Wenn man's so einfach ausdrücken kann, nicht. Aber es gibt halt
Fälle, bei denen das sinnvoll ist.
Joachim B. schrieb:>> Das ist kein reservierter Name, das ist ein Programmierfehler in der>> IDE.>> ist das nicht piepegal wenns nicht funzt?
Nicht ganz. Ein wenig Exaktheit ist auch für Ingenieure sinnvoll.
Ansonsten wäre es natürlich allemal sinnvoller, wenn Nicolas einfach
noch die Ursache der Warnung beseitigt. ;-) Man #ifdef'ed auch den
Label selbst so, dass er bei der Kombination aus #ifdefs, die zum
leeren Funktionsrumpf geführt hat, gar nicht mehr erscheint.
Jörg W. schrieb:> Ansonsten wäre es natürlich allemal sinnvoller, wenn Nicolas einfach> noch die Ursache der Warnung beseitigt. ;-) Man #ifdef'ed auch den> Label selbst so, dass er bei der Kombination aus #ifdefs, die zum> leeren Funktionsrumpf geführt hat, gar nicht mehr erscheint.
Man muß dazu sagen, daß dieses ganze Konstrukt während einer großen
Veränderungs-Session entstanden ist: Viel auskommentiert, um es
anschließend wieder neu zu schreiben.
Und wenn man gerade viel ändern muß, damit überhaupt wieder etwas geht,
sucht man so einen Fehler sehr lange.
Markus F. schrieb:> Joachim B. schrieb:>> das sah der gcc oder Atmel wohl anders, aber lass uns darüber nicht>> streiten>> Das ist kein reservierter Name, das ist ein Programmierfehler in der> IDE.
Da scheint der Parser für die Compiler-Ausgabe nicht mit "error:" als
validen Source-Code klar zu kommen. Wird "error" benutzt, gibt es diese
Warnung nicht und somit taucht der Parserfehler nicht auf.
Wenn man genau hinschaut, dann fehlt die Positionsangabe vor "error:".
Also ein Spar-Parser ;-)
Carl D. schrieb:> Also ein Spar-Parser ;-)
aus der Prüfentwicklung weiss ich das es fast unmöglich ist ALLE
möglichen Fälle abzufangen.
Ich war immer wieder überrascht welche "Tastenkombinationen" das
Prüffeldpersonal fand um mein Programm abstürzen zu lassen.
Wie sagte Cheffe mal: "manchmal muss man den Entwickler die Stücke aus
der Hand reissen"
oder anders gesagt, ich könnte unendlich lange programmieren und immer
noch unsichere Statements finden.
Ich weiss ja das mal alles auf Plausiblität prüfen müsste, aber wenn ich
einen leeren String äh Array of char habe dann prüfe ich nicht ob das
erste Zeichen 0 ist oder ob am Ende vom Array auch eine 0 steht.
Joachim B. schrieb:> aus der Prüfentwicklung weiss ich das es fast unmöglich ist ALLE> möglichen Fälle abzufangen.
Nun, andere schaffen das bei GCC allerdings völlig problemlos.
1
foo.c:2:1: error: unknown type name 'doble'
2
doble bar;
3
^
4
foo.c:1:12: warning: 'foo' defined but not used [-Wunused-variable]
5
static int foo;
6
^
Es gibt also immer ein "error:" (oder "warning:") – das traf bei Nicolas
schon mal nicht zu (der Doppelpunkt fehlte); davor steht der Name der
Datei sowie Zeilen- und Spaltennummer.
Selbst, wenn der Name der Datei Leerzeichen enthält, kann man das
recht problemlos parsen. Schwierig würde es natürlich, wenn die
Datei "foo.c:2:1: error:" heißt :-), aber sowas würde ein unter Windows
laufender Editor vermutlich ohnehin als Dateinamen ablehnen.
Jörg W. schrieb:> davor steht der Name der Datei sowie Zeilen- und Spaltennummer
Wobei die Spalte nur bei neueren Versionen angezeigt wird und dort per
-fno-show-column deaktivierbar ist.
Jörg W. schrieb:> Schwierig würde es natürlich, wenn die> Datei "foo.c:2:1: error:" heißt :-), aber sowas würde ein unter Windows> laufender Editor vermutlich ohnehin als Dateinamen ablehnen.
Sowas würde Windows selbst bereits als Dateinamen ablehnen.
Eric B. schrieb:> Jörg W. schrieb:>> Das ist völlig üblich.>> int somefunc(someargs)>> {>> blah;>> if (error condition)>> goto error;>> proceed;>>>> return 0; // success>>>> error:>> do some cleanup;>> return -1; // failure>> }>>>> Wenn man davon ein paar Fehlerbedingungen hat, spart das einfach>> ein immer tiefer schachtelndes (und dadürch völlig unübersichtlich>> werdendes) if/else-Gerippe.>> Hm? Dafür braucht man doch keine Verschachtelung?>>
1
>intsomefunc(someargs)
2
>{
3
>interror=0;
4
>
5
>// every called function returns 0 on OK, or a non-0 error code
6
>error=doSomething(someargs);
7
>if(!error)
8
>{
9
>error=doSomethingElse();
10
>}
11
>if(!error)
12
>{
13
>error=doAnotherThing();
14
>}
15
>...etc...
16
>
17
>// error handling
18
>if(error)
19
>{
20
>do_some_cleanup();
21
>}
22
>returnerror;
23
>}
24
>
> Ein guter Compiler optimiert das schon :-)
Es geht noch besser mit || chaining:
1
intsomefunc(someargs)
2
{
3
intresult;
4
if(funcA(...,&result)
5
||funcB(....,&result)
6
||funcC(....,&result))
7
some_error_handling(...);
8
return-1;
9
if(funcD(...,&result)
10
||funcE(....,&result)
11
||funcF(....,&result)){
12
do_error_handling(...),
13
return-1;
14
}
15
return0;
16
}
Dieses Pattern wird in Git häufig benutzt, gerade bei system calls.
Rolf Magnus schrieb:> Jörg W. schrieb:>> Schwierig würde es natürlich, wenn die>> Datei "foo.c:2:1: error:" heißt :-), aber sowas würde ein unter Windows>> laufender Editor vermutlich ohnehin als Dateinamen ablehnen.>> Sowas würde Windows selbst bereits als Dateinamen ablehnen.
Richtig, hauptsächlich wegen dem ':' -> Alternate Data Streams
https://de.wikipedia.org/wiki/Alternativer_Datenstrom#Beispiel
Stefan B. schrieb:> Dieses Pattern wird in Git häufig benutzt, gerade bei system calls.
Geht aber nur, wenn man zwischen den Aufrufen nichts weiter mit den
Daten machen muss.
Klar, es gibt meistens alternative Methoden, und jeder vernünftige
Programmierer wird das "goto error" wohl als letzte Variante in
Betracht ziehen. Es ist aber müßig, nun alle anderen Optionen
auszukramen: es gibt halt Fälle, in denen sowas einfach mal die
Arbeit erleichtert (der Linux-Kernel mit seinen unzähligen "goto"s
wurde ja anderweitig schon mal zitiert).