Forum: Mikrocontroller und Digitale Elektronik Was kann passieren beim Ignorieren dieser Warnung


von Rasmus W. (rassiweigel)


Lesenswert?

Hallo.

Ich habe software für den AVR ATMega 16 mit dem ICC-AVR-Compiler 
geschrieben. Habe da ein paar Fehler, die ich hier noch nicht näher 
beschreiben will, um diese Frage nicht in irgend eine Richtung zu 
leiten.

Beim compilieren des Projekts bekomme ich die Warnung:

... missing prototype

und

... declaration of `Set_DMode' does not match previous declaration at 
X:\En....


Beim compilieren ohne ANSI C Prüfung wird noch gemeldet:

... calling function without prototype may cause errors


Diese Meldungen treten auf, wenn folgender Fehler gemacht wird:

Eine Funktion wird in der C-Datei geschrieben. Diese Funktion ruft eine 
andere Funktion in der gleichen C-Datei auf.

Beide Funktionen sind in der H-Datei aufgeführt.

Die H-Datei ist nur im Hauptprogramm eingebunden, aber nicht in der 
C-Datei, in der die Funktionen stehen. Somit weiß der Compiler wohl 
nicht, wo die Funktion, die intern aufgerufen wird, steht.


Wie gesagt, der Fehler ist behoben, wenn die H-Datei in der C-Datei 
eingebunden wird.


Nur was kann geschehen, wenn man die Warnungen ignoriert und die 
Software laufen läst?

Weiß das jemand?


Ich möchte wissen, ob die Fehler, die ich beobachtet habe, darauf zurück 
zu führen sind. Leider passieren diese Fehler nicht bei mir im Labor, 
sondern nur im Feld, sodass ich das nicht einfach prüfen kann.


Gruß
Rasmus



von Karl heinz B. (kbucheg)


Lesenswert?

> Nur was kann geschehen, wenn man die Warnungen ignoriert und die
> Software laufen läst?

Alles mögliche kann passieren.
Die Warnungen bedeuten in diesem Fall ja nur, dass der Compiler
bestimmte Dinge nicht überprüfen kann. Er muss es nicht
überprüfen, der C-Standard schreibt es nicht vor, daher sind
es nur Warnungen und keine Fehler.

Nun kann es natürlich sein, dass alles in Ordnung ist und
der Programmierer aufgepasst hat. Dann passiert gar nichts,
das Program läuft und läuft und läuft.

Es kann aber auch sein, dass der Programmierer einen Fehler
eingebaut hat, den der Compiler aufgrund eben dieser nicht
durchführbaren Prüfungen nicht entdecken kann. In dem Fall
sind Tür und Tor offen. Alles mögliche kann passieren: Das
Pgm stürzt ab, deine Festplatte wird formatiert, das Ventil
zur Blutzufuhr in der angeschlossenen Dialysemaschine schliest
sich; der Patient stirbt deswegen, in dem zu steuerndem
Kernkraftwerk geht der Reaktor hoch. Stell dir einfach
den schlimmsten möglichen Fall vor und mal ihn dir noch
schlimmer aus. Genau das wird irgendwann passieren. Natürlich
nicht bei deinen Labortests, sondern erst wenn das Programm
im Einsatz ist oder du es das erste mal dem Kunden vorführst.

> Somit weiß der Compiler wohl
> nicht, wo die Funktion, die intern aufgerufen wird, steht.

Nein. Das ist dem Compiler sowieso egal. Das ist Sache des Linkers.
Für den Compiler ist nur interessant:
   * Welche Argumente nimmt die Funktion. Stimmt beim Aufruf die
     Anzahl und der Datentyp aller Argumente überein
   * Welche Argumente muessen mit einem impliziten Cast an
     die von der Funktion erwarteten Datentypen angepasst werden
     und: geht das auch.
   * Welchen Rückgabetyp hat die Funktion.
Diese Information entnimmt der Compiler dem Prototypen. Hat er
keinen zur Verfügung, dann
  * gibt es eine Warnung
  * vertraut der Compiler darauf, dass der Programmierer die
    Argumente (inklusive ev. notwendiger Casts) schon richtig
    gemacht haben wird
  * Es gelten Standard Annahmen für Argumentdatentypen. Zb.
    wird ein char immer als int übergeben und ein float wird
    auf double hochgecastet.
  * gilt die Default-Annahme, dass die Funktion einen int
    zurückliefert.

Zum Abschluss noch:
Einem Programmierer, der eine derartige Warnung ignoriert,
würde ich persönlich die Hammelbeine langziehen.

von Karl heinz B. (kbucheg)


Lesenswert?

> ... declaration of `Set_DMode' does not match previous declaration at
> X:\En....

Da haben wir doch schon was.
Dem solltest du auf jeden Fall nachgehen. Das könnte die
Ursache für Szenario 2 sein.


von Rasmus W. (rassiweigel)


Lesenswert?

Hallo.

Danke für die schnelle Antwort.

Hat nichts mit Medizin oder KAWs zu tun also keine Sorge!!!!  ;-)

Aber die Meldung
> ... declaration of `Set_DMode' does not match previous declaration at
> X:\En....

ist weg, wenn die H-Datei eingebunden ist, also die Funktion scheint 
richtig vereinbart zu sein.


Gruß
Rasmus

von Hagen R. (hagen)


Lesenswert?

Ehrlich gesagt sind exakt dies die Gründe warum ich C nicht sonderlich 
mag, im Vergleich zu anderen restriktiveren Programmiersprachen. Das 
soll jetzt kein Flamewar werden, Gott bewahre. Wenn der Compiler auf 
Grund von Fehlern des Programmieres keine exakte Entscheidung treffen 
kann dann erwarte ich das er seine Arbeit mit einer klaren Fehlermeldung 
abbricht und nicht irgendwie versucht das "nicht Machbare" denoch 
hinzubiegen.

Mir ist sehr wohl klar warum der C Compiler so und nicht anders arbeiten 
muß (benötige also keine weiteren Erklärungen), wollte eben nur darauf 
hinweisen das es dieses Verhalten ist das meiner Meinung nach im 
Vergleich zu anderen Sprachen ein "Konstruktionsfehler" darstellt.

Gruß Hagen

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

"Treat Warnings as Errors"

von Karl heinz B. (kbucheg)


Lesenswert?

>> Aber die Meldung
>> ... declaration of `Set_DMode' does not match previous declaration at
>> X:\En....
>
> ist weg, wenn die H-Datei eingebunden ist, also die Funktion scheint
> richtig vereinbart zu sein.

Das deutet darauf hin, dass du genau den Fall hattest:
  * Der Compiler hatte keinen Prototypen
  * also hat er, wie oben beschrieben, beim Aufruf
    Standardannahmen angenommen um den Aufruf compilieren
    zu können. Dabei hat sich der Compiler auch sowas ähnliches
    wie einen Prototypen für diese Funktion zurechtgelegt.
  * In weiterer Folge ist der Compiler dann auf Funktion gestossen
    und hat gemerkt, dass sein selbst generierter Prototyp nicht
    mit der tatsächlichen Implementierung übereinstimmt.
    D.h. die Standard-Annahmen, die beim Aufruf gemacht wurden
    waren falsch.

Wie gesagt: Hammelbeine langziehen. Man nimmt vom Compiler
jede Hilfe die man kriegen kann. Und man arbeitet solange
am Code, bis alle Warnungen weg sind! Eine Warnung ist wie
ein Fehler zu werten. Sie kann harmlos sein, muss aber nicht.




von Unbekannter (Gast)


Lesenswert?

> Wenn der Compiler auf Grund von Fehlern des Programmieres
> keine exakte Entscheidung treffen kann dann erwarte ich das
> er seine Arbeit mit einer klaren Fehlermeldung abbricht

Beim GCC einfach die Optionen "-Wall -Werror -pedantic-errors" setzen. 
Dann passiert genau das.

von Karl heinz B. (kbucheg)


Lesenswert?

> wollte eben nur darauf
> hinweisen das es dieses Verhalten ist das meiner Meinung nach im
> Vergleich zu anderen Sprachen ein "Konstruktionsfehler" darstellt

Ist schon OK.
Ich (und viele andere) gehe da durchaus mit dir konform.
Zur Ehrenrettung muss man halt sagen, dass einiges davon schon
auch historisch bedingt ist. Auf der Ur-PDP wa rhalt nicht massig
Platz und ich denke auch man wollte schnell einen Compiler haben.
Und wie es halt dann so ist: irgendwann ist es zu spät und man
kann ein grundlegendes Verhalten der Programmiersprache nicht
mehr ändern.

Soweit ich aber weiss (oder glaube mich zu erinnern) soll aber
in diesem speziellen Punkt eine Angleichung von C an C++
erfolgen:
* Die Implizit-Int Regel fällt weg
* Prototypen werden obligatorisch

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Der Grund für die "implizit-Int"-Regel liegt in "legacy-code", der noch 
im alten "K&R"-Stil geschrieben ist - ohne Prototypen, fast vollständig 
ohne Typüberprüfung ...

Das wurde bei der Einführung von ANSI-C bewusst zugelassen, weil sonst 
alle bis dahin geschriebenen Programme sich nicht mehr hätten übersetzen 
lassen.

Beispiel
1
my_function(a, b)
2
int a;
3
int b;
4
{
5
  dosomething(a, b);
6
  return 1;
7
}

  

von ich&er (Gast)


Lesenswert?

das verhalten, das du beschreibst passiert wenn:

...du eine funktion schreibst, diese aber im c-file (vor der 
main-funktion) nicht bekannt gemacht wird.

wenn du also zb schreibst:

void myfunction()
{
 ...
  yourCode
 ...
}

...meckert der compiler meistens, weil du die funktion vorher nicht 
bekannt gemacht hast. viele compiler gehen dann davon aus, dass die 
funktion vom typ INT ist. das meint die fehlermeldung "does not match 
previous declaration". by default ist jede funktion also INT, findet er 
jetzt wie oben geschildert eine void-funktion vor, meldet er diesen 
miss-match.

lösung also ganz einfach, die funktion ganz am anfang, dort wo auch die 
globalen variablen stehen mit typ und eventuell zu übergebenden 
variablen-typen bekanntmachen (das ist mit prototype einer funktion 
gemeint), für mein bespiel also:

-TOP OF FILE-
.
.
#include ....
.
void myfunction(void);
.
.
.
int main(){ ......


wichtig: wenn nichts an die funktion übergeben wird, dann 'void' in die 
klammern rein, ansonsten der typ(und nur der typ) der variablen, die 
werte für diese funktion entgegen nehmen.

dieser 'fehler' tritt nach meinem wissen nicht bei jedem compiler auf, 
wenn, dann liegt es aber oft an oben geschildertem szenario.

vielleicht hilft's ja, grüße....

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> wichtig: wenn nichts an die funktion übergeben wird, dann 'void' in die
> klammern rein, ansonsten der typ(und nur der typ) der variablen, die
> werte für diese funktion entgegen nehmen.

Kleiner Widerspruch:
Ich halte es für durchaus sehr sinnvoll, auch im Funktionsprototypen 
Variablennamen zu verwenden, da dies die Verwendung der 
Funktionsparameter dokumentiert. So ist mit einem Blick in die 
Headerdatei ersichtlich, wie bzw. in welcher Reihenfolge die Parameter 
zu verwenden sind.
- vorausgesetzt, derjenige, der den Funktionsprototypen geschrieben hat, 
hat sinnvolle Namen verwendet.

Manche Quellcodeeditoren verwenden die in Headerdateien gefundenen 
Prototypen auch für die Eingabeunterstützung ("code completion"), hier 
ist das Verwenden von Namen für die Parameter auch sehr sinnvoll.

von ich&er (Gast)


Lesenswert?

@rufus

ich habe im "selbstversuch" mal probiert wie sich das mit dem 
variablennamen im funktionsprototypen verhält, und es scheint 
compiler-anhängig zu sein, ob die angabe des variablennamen im 
prototypen akzeptiert wird oder nicht. mein compiler, den ich 
'windows'-anwendungen nutze erlaubt die angabe von vars, der compiler 
für den mpc(power-pc) meldet hingegen fehler und erwartet lediglich den 
typ...
..also mal so, mal so, da hilft wohl nur probieren... ;-)

grüße

von Karl heinz B. (kbucheg)


Lesenswert?

> da hilft wohl nur probieren

Oder mal ein ernstes Wort mit dem Compilerbauer sprechen.
Argumentnamen in einem Prototyp nicht zuzulassen ist nicht
nur gegen den C-Standard, sondern auch bescheuert.

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.