Forum: Compiler & IDEs GCC: Label ohne Sprung Fehler?


von Walter T. (nicolas)


Lesenswert?

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_t foo(void)
2
{
3
    uint_fast8_t status = 0;
4
5
    error:
6
    return status;
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.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

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:

von Klaus W. (mfgkw)


Lesenswert?

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.

von Walter T. (nicolas)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

Klaus W. schrieb:
> Ja, das ist nur eine Warnung.

eventuell ist ja:

-Werror
Make all warnings into errors.

gesetzt.

von Walter T. (nicolas)


Angehängte Dateien:

Lesenswert?

Peter II schrieb:
> eventuell ist ja:  -Werror [...] gesetzt.

Nein, das ist nicht der Fall.

Hier ist ein kompilierbares Minimalbeispiel im Anhang.

von Markus F. (mfro)


Lesenswert?

Ich würde mal das Label umbenennen. Möglicherweise ist bloss die IDE zu 
blöd, die Compilerausgaben richtig zu parsen und zu interpretieren.

von Walter T. (nicolas)


Lesenswert?

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 :-)

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Joachim B. schrieb:

> nun ja ein Label auch error zu nennen war keine gute Idee.

Das ist völlig üblich.
1
int somefunc(someargs)
2
{
3
   blah;
4
   if (error condition)
5
     goto error;
6
   proceed;
7
8
   return 0; // success
9
10
error:
11
   do some cleanup;
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.

: Bearbeitet durch Moderator
von Joachim B. (jar)


Lesenswert?

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

von Markus F. (mfro)


Lesenswert?

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.

von Eric B. (beric)


Lesenswert?

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
int somefunc(someargs)
2
{
3
  int error = 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
  return error; 
23
}
Ein guter Compiler optimiert das schon :-)

von Joachim B. (jar)


Lesenswert?

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?

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Markus F. (mfro)


Lesenswert?

Joachim B. schrieb:
> ist das nicht piepegal wenns nicht funzt?

mir nicht. Ich will schon wissen, über wen ich mich aufrege ;)

von Walter T. (nicolas)


Lesenswert?

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.

von Carl D. (jcw2)


Lesenswert?

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 ;-)

von Joachim B. (jar)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

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.

von Max M. (stefan_b858)


Lesenswert?

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
> int somefunc(someargs)
2
> {
3
>   int error = 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
>   return error;
23
> }
24
>
> Ein guter Compiler optimiert das schon :-)

Es geht noch besser mit || chaining:
1
int somefunc(someargs)
2
{
3
    int result;
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
    return 0; 
16
}

Dieses Pattern wird in Git häufig benutzt, gerade bei system calls.

von Kaj (Gast)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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).

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.