Moin,
Grad' bin ich in eine lustige Fallgrube gestolpert - da lass ich doch
gerne die Experten sich dran ergoetzen:
Folgende Dateien
main.c:
1
/* compile with:
2
gcc -I. -Wall -Wextra -pedantic bla.c main.c
3
*/
4
5
#include<bla.h>
6
7
intmain(){
8
returnbla();
9
}
bla.c:
1
#include<stdio.h>
2
#include<bla.h>
3
4
intbla(int*blupp){
5
printf("will access %p\n",(void*)blupp);
6
fflush(stdout);
7
*blupp=42;
8
return0;
9
}
bla.h:
1
intbla();
kompilieren ohne jeden Mecker zu einem executable, was dann dank nicht
zusammenpassender Funktion/Prototyp in bla.c und bla.h irgendwo in den
Speicher schreibt.
Wasnichtallesschiefgehenkann...
Gruss
WK
>kompilieren ohne jeden Mecker
Wirklich? Mit welchem Compiler?
MIS(T)RA-C Rule No 42:
-If you get too many compile-warnigs, adjust your warning level
settings!
Dergute W. schrieb:> int bla();
Naja, das ist halt so, wenn man "int bla();" statt "int bla(void);"
schreibt.
Das "int bla();" hat schon seinen Verwendungszweck, ist aber hier fehl
am platz.
Ich würde beim Compilieren ausserdem noch "-std=c99" oder "-std=c11"
hinzufügen, sonst weiss man nie so genau, welche Programmiersprache das
jetzt wieder sein soll.
DPA schrieb:> Das "int bla();" hat schon seinen Verwendungszweck, ist aber hier fehl> am platz.
Das würde mich jetzt aber mal interessieren. Bin ja immer noch am dazu
lernen. Welcher Verwendungszweck wäre das genau?
Das im obigen Beispiel der Compiler keinen Fehler auswirft, wundert mich
allerdings schon.
naja c compiler nehmen es mit den prototypen (und pointer typen!) nicht
soo genau...
ich hätte mir da aber auch eine warning erhofft...
der c++ compiler sieht es jedenfalls nicht so lax:
bash-4.3$ gcc -x c++ -I. -Wall -Wextra -pedantic bla.c main.c
/tmp/ccTUJjgt.o: In function `main':
main.c:(.text+0x5): undefined reference to `bla()'
collect2: error: ld returned 1 exit status
damit ist meine welt wieder in ordnung :)
73
Ste N. schrieb:> Das würde mich jetzt aber mal interessieren. Bin ja immer noch am dazu> lernen. Welcher Verwendungszweck wäre das genau?
Code ohne Prototypes. Die gibt es erst seit C89. Die Deklaration "int
bla();" ist nicht etwa eine Funktion ohne Parameter, sondern lässt die
Frage nach den Parametern völlig offen.
1
> gcc -c -Wmissing-prototypes test.c
2
4.c:3:5: warning: no previous prototype for ‘bla’ [-Wmissing-prototypes]
3
int bla(int blubb)
4
^
Hans schrieb:> damit ist meine welt wieder in ordnung :)
C++ ist in dieser Frage anders als C.
Dergute W. schrieb:> kompilieren ohne jeden Mecker zu einem executable
Ja, der Compiler nimmt an daß Du Code aus der Ära von Kerninghan oder
Ritchie schreibst. Mit Spaß hat das nichts zu tun, Prototypen ohne
Argumentliste war gültige Syntax.
Man kann dem Compiler mitteilen daß er meckern soll, zum Beispiel mit
-Wstrict-prototypes. (leider nicht in -Wall und -Wextra enthalten um die
Kompatibilität mit altem Code zu wahren)
Frank M. schrieb:> Also: Option -Wstrict-prototypes immer mit angeben.
Und/oder sich einfach angewöhnen, nie eine Deklaration foo() zu
schreiben, sondern immer foo(void). In C++ wäre zwar (anders als in
C) beides dasselbe, aber es ist eben auch dort nicht verboten, das
„void“ explizit zu schreiben.
Jörg W. schrieb:> Und/oder sich einfach angewöhnen, nie eine Deklaration foo() zu> schreiben, sondern immer foo(void).
Ich muss zugeben, dass ich das void in einer Deklaration ab und zu
einfach vergesse. Das kommt zwar selten vor, fällt aber dank
-Wstrict-prototypes sofort auf.
Hans schrieb:> undefined reference to `bla()'>> damit ist meine welt wieder in ordnung :)
Das ist jetzt aber auch eine extem blöde Fehlermeldung, die Anfängern in
diesem einfachen Fall und auch Erfahreneren in komplexeren Fällen in die
Irre führt.
Natürlich gibt es bla, nur halt in der Form bla(int *) statt bla(). Ein
bischen mehr Gehirnschmalz könnte gcc da schon einsetzen, bzw. seine
Erbauer.
MaWin schrieb:> Hans schrieb:>> undefined reference to `bla()'>>>> damit ist meine welt wieder in ordnung :)>> Das ist jetzt aber auch eine extem blöde Fehlermeldung
Naja, wenn der Programmierer gleich an zwei Stellen sagt, er möchte eine
Funktion bla ohne Argumente, nämlich sowohl
- im Protoyp als auch
- im Aufruf,
glauben ihm Compiler und Linker das und gehen davon aus, dass einfach
nur vergessen wurde, die Funktion zu implementieren bzw. dem Linker das
entsprechende Modul oder die Bibliothek bekannt zu geben.
Nur wenn Aufruf und Prototyp(en) überhaupt nicht zusammenpassen, zeigt
dies der Compiler an und listet bei überladenen Funktionen die möglichen
Kandidaten auf.
A. K. schrieb:> Ste N. schrieb:>> Das würde mich jetzt aber mal interessieren. Bin ja immer noch am dazu>> lernen. Welcher Verwendungszweck wäre das genau?>> Code ohne Prototypes. Die gibt es erst seit C89. Die Deklaration "int> bla();" ist nicht etwa eine Funktion ohne Parameter, sondern lässt die> Frage nach den Parametern völlig offen.
Aber wozu braucht man das heute noch? In C++ wurde es abgechafft, und in
C ist es meiner Meinung nach nur drin, um alten Code nicht inkompatibel
zu machen.
>> gcc -c -Wmissing-prototypes test.c> 4.c:3:5: warning: no previous prototype for ‘bla’ [-Wmissing-prototypes]> int bla(int blubb)> ^
Ich nehme da gleich -Werror=missing-prototypes. Dann ist es wie in C++.
A. K. schrieb:> mh schrieb:>> Der Compiler kann nicht warnen,>> Wenn er bla.c übersetzt, sieht er beides. Da warnt er, wenn man ihn> lässt.
Da ist aber formal nichts falsch dran.
MaWin schrieb:> Hans schrieb:>> undefined reference to `bla()'>>>> damit ist meine welt wieder in ordnung :)>> Das ist jetzt aber auch eine extem blöde Fehlermeldung, die Anfängern in> diesem einfachen Fall und auch Erfahreneren in komplexeren Fällen in die> Irre führt.
Es ist allerdings auch eine unglückliche Situation.
> Natürlich gibt es bla, nur halt in der Form bla(int *) statt bla().
der Programmierer hat dem Compiler gesagt: Es gibt eine Funktion bla(),
die irgendwo anders implementiert ist. Sie ist aber nirgends anders
implementiert. bla(int*) ist zunächst mal eine andere Funktion. So kann
dann erst der Linker erkennen, dass die gewünschte Funktion gar nicht
existiert.
Rolf M. schrieb:> A. K. schrieb:>> mh schrieb:>>> Der Compiler kann nicht warnen,>>>> Wenn er bla.c übersetzt, sieht er beides. Da warnt er, wenn man ihn>> lässt.>> Da ist aber formal nichts falsch dran.
Deswegen auch eine Warnung. Ich habe lange überlegt, ob mir ein Beispiel
einfällt, bei dem die Warnung nicht gerechtfertigt ist und mich stören
würde. Mir ist allerdings keins eingefallen.
Rolf M. schrieb:> Aber wozu braucht man das heute noch?
Insbesondere ist natürlich die Frage, warum die Warnung nicht
standardmäßig an ist.
> In C++ wurde es abgechafft,
Die hatten es einfacher: dort gab es das nie.
Jörg W. schrieb:> Frank M. schrieb:>> Also: Option -Wstrict-prototypes immer mit angeben.>> Und/oder sich einfach angewöhnen, nie eine Deklaration foo() zu> schreiben, sondern immer foo(void). In C++ wäre zwar (anders als in> C) beides dasselbe, aber es ist eben auch dort nicht verboten, das> „void“ explizit zu schreiben.
In C++ haben aber die Funktionen foo() und foo(int) intern nicht den
gleichen Namen. Das hilft dem Linker ungemein.
Yalu X. schrieb:> Naja, wenn der Programmierer gleich an zwei Stellen sagt, er möchte eine> Funktion bla ohne Argumente
Sagt er nicht. In der Deklaration steht nicht void. Er sagt also nur,
dass er über die Parameter nichts aussagen will.
Rolf M. schrieb:> der Programmierer hat dem Compiler gesagt: Es gibt eine Funktion bla(),> die irgendwo anders implementiert ist. Sie ist aber nirgends anders> implementiert. bla(int*) ist zunächst mal eine andere Funktion. So kann> dann erst der Linker erkennen, dass die gewünschte Funktion gar nicht> existiert
Diese Meinung vertreten nur die Computernerds, die kein Gehirn für die
wirkliche Welt mehr übrig haben. Die begründen dann durch Erklärung der
internen Mechanismen, warum sich der Computer so doof verhält, dass der
Anwender sich die Haare rauft. An statt das Verhalten des Computers
durch geeignete interne Strukturierung an die Erwartungshaltung der
Anwender anzupassen.
mh schrieb:> Deswegen auch eine Warnung. Ich habe lange überlegt, ob mir ein Beispiel> einfällt, bei dem die Warnung nicht gerechtfertigt ist und mich stören> würde. Mir ist allerdings keins eingefallen.
Ich habe wahrscheinlich noch Code aus den 80ern auf Disk. Allerdings
halte ich es es für zumutbar, eventuelle Makefiles ggf so zu tunen, dass
ein heutiger Compiler damit zurecht kommt. Zumal solcher Code ggf auch
noch gegen die integer conversion rules von ANSI-C verstösst.
MaWin schrieb:> Rolf M. schrieb:>> der Programmierer hat dem Compiler gesagt: Es gibt eine Funktion bla(),>> die irgendwo anders implementiert ist. Sie ist aber nirgends anders>> implementiert. bla(int*) ist zunächst mal eine andere Funktion. So kann>> dann erst der Linker erkennen, dass die gewünschte Funktion gar nicht>> existiert>> Diese Meinung vertreten nur die Computernerds, die kein Gehirn für die> wirkliche Welt mehr übrig haben. Die begründen dann durch Erklärung der> internen Mechanismen, warum sich der Computer so doof verhält, dass der> Anwender sich die Haare rauft.
Ja, ich weiß, dass viele Leute in der "wirklichen Welt" der technische
Grund, warum etwas nicht so funktioniert, wie sie es gerne hätten, nicht
interessiert. Die wollen halt, dass die "Computernerds" ihnen ihre
Probleme lösen und ansonsten die Klappe halten.
> An statt das Verhalten des Computers durch geeignete interne> Strukturierung an die Erwartungshaltung der Anwender anzupassen.
Man sollte also die komplette grundlegende Struktur, wie Compiler und
Linker zusammen arbeiten, über den Haufen werfen, damit eine
anfängerfreundlichere Warnung ausgegeben wird?
Rolf M. schrieb:> Man sollte also die komplette grundlegende Struktur, wie Compiler und> Linker zusammen arbeiten, über den Haufen werfen, damit eine> anfängerfreundlichere Warnung ausgegeben wird?
Muss man nicht. Der Compiler macht ja bei Fehlermeldungen mittlerweile
auch solche Heuristiken ("candidates are …"), das könnte durchaus auch
der Linker tun. Hat sich offenbar nur noch niemand gemüßigt gefühlt.
Hat natürlich auf der anderen Seite auch den Effekt, dass einem der
Linker plötzlich 30 Kandidaten um die Ohren werfen könnte, die alle
"irgendwie passen könnten". Ist die Frage, ob damit dem Anwender dann
wirklich mehr geholfen wäre.
MaWin schrieb:> Yalu X. schrieb:>> Naja, wenn der Programmierer gleich an zwei Stellen sagt, er möchte eine>> Funktion bla ohne Argumente>> Sagt er nicht. In der Deklaration steht nicht void. Er sagt also nur,> dass er über die Parameter nichts aussagen will.
Es ging in der Aussage von Hans, auf die du dich bezogst, nicht um C,
sondern um C++. Hier noch einmal die Historie in der Übersicht:
Hans schrieb:> der c++ compiler sieht es jedenfalls nicht so lax:>> bash-4.3$ gcc -x c++ -I. -Wall -Wextra -pedantic bla.c main.c> /tmp/ccTUJjgt.o: In function `main':> main.c:(.text+0x5): undefined reference to `bla()'MaWin schrieb:> Das ist jetzt aber auch eine extem blöde FehlermeldungYalu X. schrieb:> Naja, wenn der Programmierer gleich an zwei Stellen sagt, er möchte eine> Funktion bla ohne Argumente, ...
Rolf M. schrieb:> Man sollte also die komplette grundlegende Struktur, wie Compiler und> Linker zusammen arbeiten, über den Haufen werfen
Nein man muss nicht, auch nach Typemangling stehen die Funktionsnamen
noch drin und man kann gleichlautende erkennen. Man muss nur ein paar
weitere Codezeilen schreiben, also seine Faulheit überwinden, "Wieso
ändern, kommt doch irgendeine Meldung, ich mach jetzt Feierabend und
geh zocken"
> damit eine> anfängerfreundlichere Warnung ausgegeben wird?
Damit eine sinnvolle Meldung ausgegeben wird.
Microsoft hat bei seinem Compiler auch gelernt. Noch nicht perfekt, aber
viel besser als früher.
MaWin schrieb:> Rolf M. schrieb:>> Man sollte also die komplette grundlegende Struktur, wie Compiler und>> Linker zusammen arbeiten, über den Haufen werfen>> Nein man muss nicht, auch nach Typemangling stehen die Funktionsnamen> noch drin und man kann gleichlautende erkennen. Man muss nur ein paar> weitere Codezeilen schreiben, also seine Faulheit überwinden,
Dann tu das doch einfach. Die Binutils-Entwickler freuen sich sicher
über einen Patch.
>> damit eine anfängerfreundlichere Warnung ausgegeben wird?>> Damit eine sinnvolle Meldung ausgegeben wird.> Microsoft hat bei seinem Compiler auch gelernt. Noch nicht perfekt, aber> viel besser als früher.
Dafür haben sie sie sich bei allem anderem im Bezug auf die
Fehlermeldungen noch weiter verschlechtert. Aber das ist ein genereller
Trend, nicht nur bei Microsoft. Früher kam wenigstens noch ein bisschen
Information, heute kann man froh sein, wenn überhaupt noch eine Meldung
kommt, in der dann sowas hilfreiches steht wie "Huch, etwas ist schief
gelaufen", wahlweise mit dem Vorschlag, sich an den Administrator zu
wenden oder es später nochmal zu versuchen.
Rolf M. schrieb:> Aber das ist ein genereller> Trend, nicht nur bei Microsoft. Früher kam wenigstens noch ein bisschen> Information,
Das liegt daran daß heute im Gegensatz zu früher 99% der
Computerbenutzer Normalsterbliche sind die erwarten daß es
funktioniert[TM] wie eine Kaffeemaschine oder ein elektrischer
Dosenöffner ohne auch nur im Geringsten an irgendwelchen Details der
genauen Abläufe interessiert zu sein. Es gibt für diesen Personenkreis
nur zwei Zustände: "funktioniert" und "funktioniert nicht", weder das
"wie" noch das "warum" spielen für die irgendeine Rolle.
Das eine Prozent die das anders sehen (und aus dem sich in der guten
alten Pionierzeit[TM] 100% der Computernutzer rekrutiert haben) weichen
heute auf Linux aus weil sie die zunehmende Verdummung und Entmündigung
des Anwenders nicht mehr ertragen können.
Bernd K. schrieb:> Das liegt daran daß heute im Gegensatz zu früher 99% der> Computerbenutzer Normalsterbliche sind die erwarten daß es> funktioniert[TM] wi
Glaubst du wirklich, dass diese Personen einen C-Compiler benutzen? Und
wenn ja, benutzen die den gcc?
mh schrieb:> Glaubst du wirklich, dass diese Personen einen C-Compiler benutzen?
Ich bezog mich darauf daß mein Vorposter sich darauf bezog daß ein
genereller Trend bei Fehlermeldungen zu beobachten sei. Das harmoniert
auch gut mit der vielbesungenen Wegwerfgesellschaft.
Moin,
Mike schrieb:>>kompilieren ohne jeden Mecker>> Wirklich?
Nein, war nur Spass. Eigentlich will ich viel lieber viele LEDs ohne
Vorwiderstand parallelschalten und damit einen Lauflichtblinker an
meinen frisierten Plastikroller tackern....
:-)
SCNR,
WK