Präambel: Mein C ist vielleicht etwas eingerostet; ich habe etwa 1993 angefangen, C-Programme zu schreiben - die Compiler mögen damals anders gewesen sein, aber ich erinnere mich, dass der Compiler abbrach, wenn man versuchte, auf eine C-Funktion zu verweisen, die nicht deklariert war. Dies ist aus dem Gedächtnis.
Derzeit bin ich ratlos, warum GCC (4.4.3) ist so verzeihend auf mich, wenn ich [absichtlich] mismatch oder weglassen Deklaration von bar
unten, mit seiner Definition in bar.c
. Da der Compiler mich nicht warnt, kommt es zur Laufzeit des Programms zu einem fatalen Adressierungsfehler -- da bar
eine Adresse sucht und eine Ganzzahl erhält, wird diese Ganzzahl als Adresse de-referenziert.
Ein strenger Compiler, so würde ich meinen, würde mich mit einem Fehler abbrechen. Übersehe ich etwas? Meine Build-Befehlszeile lautet wie folgt:
cc -o foobar -g -Wall -std=c99 -fexec-charset=ISO-8859-1 -DDEBUG foo.c bar.c
Mit foo.c
:
int main() {
int a;
bar(a);
return 0;
}
y bar.c
:
void bar(int * a) {
*a = 1;
}
Ich habe absichtlich auf die Angabe von bar
und, wie bereits erwähnt, absichtlich eine Ganzzahl (kann eigentlich alles sein) anstelle einer Adresse übergeben, die die eigentliche Definition sonst vorschreiben würde. Weil $(CC)
hält mich nicht auf, ich lande mit einem Segmentierungsfehler (x86, Ubuntu 10.04). Ich bin mir bewusst, dass eine konforme C (C99?) Compiler würde implizit eine erstellen int bar(void)
Erklärung für bar
wenn sonst keine gefunden werden, aber das ist in diesem Fall offensichtlich nicht das, was ich will!
Ich möchte mich vor der Art von Fehlern schützen, bei denen ich den menschlichen Fehler begehe, Deklarationen und Definitionen nicht in Einklang zu bringen oder erstere ganz wegzulassen.
Ich habe versucht, den Compiler stattdessen einfach ohne den Verknüpfungsschritt aufzurufen (mit der Option -c
Schalter) -- aber das spielt keine Rolle, da das Kompilieren trotzdem mit Warnungen erfolgreich ist. Der Linker könnte sich zwar beschweren, aber ich möchte der Compiler um mich aufzuhalten vor das passiert.
I nicht eigentlich alle meine Warnungen in Fehler umwandeln möchte (z. B. mit -Werror
), denn:
- Ich könnte den falschen Namen eingegeben haben.
float bar(double a);
an der Spitze vonfoo.c
zu kompilieren, was die Warnung vollständig beseitigen würde, aber nichts an der Tatsache ändert, dass das resultierende Programm abstürzt; leider kann ein Programm, das ohne Warnungen erfolgreich kompiliert wird (sogar mit der-Wall
Schalter), ist aber dennoch fehlerhaft - Ich habe und werde andere Arten von Warnungen haben, die Warnungen bleiben sollten und nicht die erfolgreiche Erstellung des Programms verhindern
- Es ginge um die Auswirkungen des Problems, nicht um das Problem selbst.
- Es ist nicht nur der Typen von Warnungen, sondern auch bestimmte Fälle davon; ich würde eine bestimmte Warnung nicht in einen Fehler umwandeln wollen, weil das in einigen Fällen nicht zutreffen würde; das wäre eine zu "grobe" Lösung, die die Besonderheiten und den Kontext, in dem die Warnung auftrat, nicht berücksichtigt