Forum: Compiler & IDEs Prüfen ob -Werror gesetzt (Preprocessor)


von Thomas B. (nichtessbar)


Lesenswert?

Hallo,

habe gerade in einer neuen Version einer Bibliothek von mir einen 
Prototypen einer Callback-Methode verändert, der an eine Variable als 
Zeiger auf eine Funktion zugewiesen wird.

Voher war's
1
unsigned char m3sCmdHandler(const unsigned char* pCmd, unsigned char pLastControlByte, unsigned char pUpperBound, unsigned char pAllowsResponse);

Jetzt neu ist er:
1
uint8_t m3sCmdHandler(const void* rSlave, const unsigned char* pCmd, unsigned char pControlbyte, unsigned char pUpperBound, unsigned char pAllowsResponse);

Verwendet wird das dann wie folgt:
1
slave->CommandHandler   = m3sCmdHandler;


Compiliert man nun Code, der mit einer alten Bibliotheksversion (und 
somit dem alten Protoypen) erstellt wurde, lässt sich das problemlos 
machen, es wird - richtigerweise - ein Warning generiert:
1
assignment from incompatible pointer type [enabled by default]


So, jetzt kommt das Problem; in älteren AVR-Studios und der Konsole ist 
das kein Problem, da bekommt man ja Warnings angezeigt. In den neuen 
Studios (Atmel Studio 5.0 - 6.0) macht sich das Studio defaultmäßig 
nicht die Mühe, wegen eines Warnings in das "Error List"-Output-Fenster 
zu wechseln, ergo viele Programmierer werden das Warning erstmal 
übersehen und sich wundern warum der Callback auf einmal nicht mehr 
richtig funktioniert (vorausgesetzt haben Debugmöglichkeit, sonst ist 
der Fehler noch viel schwerer nachzuvollziehen)


Mein Ansatz wäre jetzt, den Benutzer irgendwie zu zwingen, avr-gcc mit 
-Werror aufzurufen, was ohnehin best practice wäre, und falls er das 
Flag nicht verwendet, eine entsprechende Meldung à la

"If using TBL-AVR library it is highly recommended to compile with 
-Werror set. To ignore this error, pass -DIGNORE_TBL_WARNINGS to 
avr-gcc"

ausgeben

Dafür bräuchte ich jetzt in meinem Header so ein Konstrukt
1
#ifndef IGNORE_TBL_WARNINGS
2
  #ifndef __WERROR__
3
    #error "If using TBL-AVR library it is highly recommended to compile with -Werror set. To ignore this error, pass -DIGNORE_TBL_WARNINGS to avr-gcc"
4
  #endif
5
#endif


Ich hab bereits versucht mit folgendem Compileraufruf nach einem Symbol 
zu suchen;

avr-gcc -Werror -mmcu=atmega88 -DF_CPU=20000000UL -E -dM testfile.c

Liefert eine elendslange Liste, die aber - sofern ich nichts übersehe - 
nichts brauchbares in dieser Sache enthält.


Weiß jemand ob - und wenn ja welches - Symbol definiert wird, wenn der 
Compiler mit der -Werror Option aufgerufen wird.


Alternativvorschläge wie man in diesem Fall den 
"Endkunden-Programmierer" mit der Nase auf sein Problem des veralteten 
Codes stoßen kann sind natürlich ebenfalls sehr willkommen.

LG und Danke
Thomas

von Thomas B. (nichtessbar)


Angehängte Dateien:

Lesenswert?

#define Symbolliste des oben erwähnten Compileraufrufs

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Du könntest die Lib mit einer Version versehen und diese abtesten.

Wenn du erst in der aktuellen Version damit anfängst weißt du immerhin, 
daß es sich um eine ältere als die aktuelle Version handelt wenn keine 
Version vorhanden ist.

von Rolf Magnus (Gast)


Lesenswert?

Thomas Bergmüller schrieb:
> slave->CommandHandler   = m3sCmdHandler;

Warum änderst du nicht einfach den Namen "CommandHandler" in irgendwas 
anderes? Dann kommt beim Zuweisungsversuch eine Fehlermeldung, ohne von 
irgendwelchen Compiler-Flags abhängig zu sein.

von Thomas B. (nichtessbar)


Lesenswert?

Danke für die schnellen Antworten!

@ Johann:
Version gibt's da drinnen schon, aber bringt in dem Fall nichts weil es 
ja darum geht, dass alter fremder Code der vor ~ 1 Jahr geschrieben wird 
wieder compiliert wird und eine zuweisung nicht mehr aktuell ist.. da 
müsste ja dann eigentlich ein

#if VERSION == 2
  slave.CommandHandler = cmdHandler_alt;
#else
  slave.CommandHandler = cmdHandler_neu;
#endif

im Anwendercode zu finden sein, und das ist ja nicht der Fall.

Warning wird ja richtig ausgegeben, nur verschwindets in den neueren 
Atmelstudios leider und das möcht ich irgendwie abfangen.


@Rolf
Läuft im Endeffekt wieder aufs gleiche raus leider;

Ändere ich CommandHandler auf CommandCallback kommt es zu folgendem 
Szenario:

1.) CompilerError 'DevComSlave_t' has no member named 'CommandHandler'

2.) Benutzer ändert CommandHandler auf CommandCallback weil er das in 
der Doku bzw. Headerfile so findet, denkt aber nicht daran dass sich der 
Prototyp auch geändert hat, sprich er lässt die Zuweisung selbst 
unverändert.

3.) Compilieren funktioniert, nur dass das eigentliche Problem, nämlich 
der falsche Prototyp der zugewiesenen Funktion, noch immer besteht (und 
das entsprechende Warning wieder im Hintergrund untergeht). Quasi 
gleiches Problem mit anderer Bezeichnung



Ich kann natürlich in der Doku festlegen, dass es empfohlen wird, mit 
-Werror zu compilieren, aber das macht dann die Hälfte nicht und bei mir 
läufts Telefon heiß... ist eigentlich ein privates Open-Source projekt, 
wird aber mittlerweile von meiner Firma in fast allen Projekten 
verwendet und auch von Projektpartnern und anderen Firmen gibt es einige 
Produkte die die Kommunikation auf der Lib aufbauen... von daher soll 
das relativ hieb und stichfest sein ;)

von Rolf Magnus (Gast)


Lesenswert?

Thomas Bergmüller schrieb:
> @Rolf
> Läuft im Endeffekt wieder aufs gleiche raus leider;
>
> Ändere ich CommandHandler auf CommandCallback kommt es zu folgendem
> Szenario:
>
> 1.) CompilerError 'DevComSlave_t' has no member named 'CommandHandler'
>
> 2.) Benutzer ändert CommandHandler auf CommandCallback weil er das in
> der Doku bzw. Headerfile so findet, denkt aber nicht daran dass sich der
> Prototyp auch geändert hat, sprich er lässt die Zuweisung selbst
> unverändert.

An der Stelle im Header und in der Doku muß natürlich stehen, daß sich 
der Prototyp geändert hat. Wer das dann nicht liest und auch noch alle 
Warnungen ignoriert (egal, ob die automatisch angezeigt werden oder man 
noch irgendwo klicken muß), der ist ja nun wirklich selbst schuld. Ein 
bischen Denkfähigkeit würde ich da ich schon voraussetzen.

von Thomas B. (nichtessbar)


Lesenswert?

Falls jemand das Problem nachstellen möchte:

- Kompilierbares Projekt (Atmel Studio 6.0) im Anhang

ODER
- C-Datei OldPrototypeProblem.c im Anhang, compilieren mit Zusatzflags 
(zu den üblichen)
1
avr-gcc -ltbl -DF_CPU=20000000UL


Was braucht man dazu?
Alles hier in der Wiki erklärt: geht wirklich schnell und unkompliziert 
;)
http://78.47.193.140/engineering/lib/issues/wiki/HowToUseTBL-AVR

Mit Installation der Version 1.2.3 Beta tritt das Warning auf.


Aktuelle Issues und Details finden sich hier:
http://78.47.193.140/engineering/lib/issues/tblavr/issues/3
http://78.47.193.140/engineering/lib/issues/tblavr/issues/5

von Thomas B. (nichtessbar)


Lesenswert?

@ Rolf
Ja möchte man meinen ;) In der HowTo ist das -Werror flag eh auch schon 
empfohlen... Aber das ist halt vielen zu lästig wenn jede unused 
variable das Übersetzen verhindert... deswegen muss man sie zu ihrem 
Glück zwingen oder zumindest zwingend darauf hinweisen dass das 
strengstens empfohlen ist..

Für den Hobbyisten ist das vmtl. kein Problem, in der Wirtschaft wird 
aber erfahrungsgemäß wenn was nicht funktioniert gleich mal zum Telefon 
gegriffen und beschwert bzw. nachgefragt bevor sich wer die Mühe "macht" 
die Doku oder zu lesen

Muss immer alles ein bisschen bullet-proof sein, und gutes Deployment 
und Rückwärtskompabilität bzw. entsprechende Fehler machen meiner 
Meinung auch den Unterschied zwischen guten und schlechten Bibliothekten 
aus - erspart dem Anwender einfach viel Ärger und stundenlanges Suchen 
am falschen Ort.

Um ehrlich zu sein, ich hab anfangs bei einem Projekt auch übersehen den 
Handler zu ändern und dann 2h darauf verwendet, die restliche Software 
zu debuggen bevor ich angefangen hab in der Bibliothek den Fehler zu 
suchen.

von Thomas B. (nichtessbar)


Angehängte Dateien:

Lesenswert?

Thomas Bergmüller schrieb:
> - Kompilierbares Projekt (Atmel Studio 6.0) im Anhang
>
> ODER
> - C-Datei OldPrototypeProblem.c im Anhang, compilieren mit Zusatzflags

Anhang vergessen...

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


Lesenswert?

Thomas Bergmüller schrieb:
> In den neuen
> Studios (Atmel Studio 5.0 - 6.0) macht sich das Studio defaultmäßig
> nicht die Mühe, wegen eines Warnings in das "Error List"-Output-Fenster
> zu wechseln, ...

Dann kannst du wohl nur die Benutzung von AVR Studio 5 oder Atmel
Studio 6 als "unsupported platform" für deine Software deklarieren.

> Liefert eine elendslange Liste, die aber - sofern ich nichts übersehe -
> nichts brauchbares in dieser Sache enthält.

Richtig.  Kannst du ganz einfach verifizieren: einmal mit, einmal
ohne -Werror die Liste erzeugen und beide vergleichen.  Sie sind
identisch.  Damit kommt eine präprozessorbasierte Lösung nicht in
Frage.

von Karl H. (kbuchegg)


Lesenswert?

Thomas Bergmüller schrieb:

> Ändere ich CommandHandler auf CommandCallback kommt es zu folgendem
> Szenario:
>
> 1.) CompilerError 'DevComSlave_t' has no member named 'CommandHandler'
>
> 2.) Benutzer ändert CommandHandler auf CommandCallback weil er das in
> der Doku bzw. Headerfile so findet, denkt aber nicht daran dass sich der
> Prototyp auch geändert hat, sprich er lässt die Zuweisung selbst
> unverändert.
>
> 3.) Compilieren funktioniert, nur dass das eigentliche Problem, nämlich
> der falsche Prototyp der zugewiesenen Funktion, noch immer besteht (und
> das entsprechende Warning wieder im Hintergrund untergeht). Quasi
> gleiches Problem mit anderer Bezeichnung


Der Part ist mir nicht klar.
Das sollte eigentlich nicht compilieren. Denn in einem Funktionspointer 
sind auch die Anzahl und Datentypen der Argumente Bestandteil des 
Datentyps des Funktionspointers. Damit ist das die Zuweisung eines 
Pointers an einen anderen Pointer mit unterschiedlichem Datentyp.

Und das sollte IMHO eigentlich ein Fehler sein. Im Grund nichts anderes 
als

  int * pA;
  double * pB;

  pA = pB;

nur eben mit Funktionspointern.


Klar, mit einem Cast kann man das immer noch aushebeln. Aber wer Pointer 
umcastet, sollte schon sehr genau wissen, was er tut.

von Rolf Magnus (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Denn in einem Funktionspointer sind auch die Anzahl und Datentypen der
> Argumente Bestandteil des Datentyps des Funktionspointers. Damit ist das
> die Zuweisung eines Pointers an einen anderen Pointer mit
> unterschiedlichem Datentyp.
> Und das sollte IMHO eigentlich ein Fehler sein.

Ist es aber in C nicht.

> Im Grund nichts anderes als
>
>   int * pA;
>   double * pB;
>
>   pA = pB;
>
> nur eben mit Funktionspointern.

Und auch da kommt nur eine Warnung.

von Thomas B. (nichtessbar)


Lesenswert?

Ja, ist Bestandteil des Datentyps und die Zuweisung natürlich falsch. 
GCC behandelt das aber - in diesem Fall sehr zu meinem Bedauern - nur 
mit einem Warning und keinem Error.

Gibt ja auch weniger schwere Fälle wo's nur syntaktisch nicht schön ist, 
z.b. unsigned char und char Arrays (solange nur bitweise und nicht 
arithmetisch verwendet wird), Parameter im Prototyp mit und ohne 
vorangestelltem const usw.

Genau aus dem Grund, weil's gcc eben nicht macht, es in diesem Fall aber 
zu schwerwiegenden und vor allem schwer diagnostizierbaren Fehlern kommt 
(ist ja genau der Übergabepunkt aus der Library, die nicht gedebuggt 
werden kann) und dem Anwendungsprogramm, möchte ich das Warning 
irgendwie verschärfen, sodass es nicht so leicht übergangen werden kann

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Thomas Bergmüller schrieb:
> Ja, ist Bestandteil des Datentyps und die Zuweisung natürlich falsch.
> GCC behandelt das aber - in diesem Fall sehr zu meinem Bedauern - nur
> mit einem Warning und keinem Error.
>
> Gibt ja auch weniger schwere Fälle wo's nur syntaktisch nicht schön ist,
> z.b. unsigned char und char Arrays (solange nur bitweise und nicht
> arithmetisch verwendet wird), Parameter im Prototyp mit und ohne
> vorangestelltem const usw.
>
> Genau aus dem Grund, weil's gcc eben nicht macht, es in diesem Fall aber
> zu schwerwiegenden und vor allem schwer diagnostizierbaren Fehlern kommt
> (ist ja genau der Übergabepunkt aus der Library, die nicht gedebuggt
> werden kann) und dem Anwendungsprogramm, möchte ich das Warning
> irgendwie verschärfen, sodass es nicht so leicht übergangen werden kann

Aus genau dem Grund gibt's -Werror.  Und wenn einem die 
Holzhammermethode zu viel ist, kann man auch einzelne Warnungen im 
Fehler wandeln mit -Werror=...

Wer Diagnosticsc nicht nutzen oder beachten möchte, der muss sich halt 
im erzeugten Code den Wolf suchen...

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.