GCC: Label ohne Sprung Fehler?

OP #4506958
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.
#4506968
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.
Moderator Persönliche Seite #4507015
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.
#4507094
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 :-)
Moderator Persönliche Seite #4507131
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.
OP #4507153
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.
#4507293
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 ;-)
#4507535
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.
Moderator Persönliche Seite #4507547
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.
#4507714
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.
Gast #4507782
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
Moderator Persönliche Seite #4507805
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).

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