Grundsatzdiskussionen zu C
-
Bezüglich rev. 347 entspannte sich eine vielleicht interessante Diskussion, die aus einem Zwiespalt zwischen Theorie und Praxis herrührt:
Es ging um folgende praktische Enstcheidung:
Ausgangspunkt:
pci.c:uint8_t network_buffer[8192+16]; uint32_t BaseAddressRTL8139_IO; uint32_t BaseAddressRTL8139_MMIO; pciDev_t pciDev_Array[PCIARRAYSIZE];
Vorschlag von mir, diese hier nicht initialisierten Variablen in dieser Form in den passenden Header (rtl8139.h bzw. pci.h) zu verschieben, wurde von MrX klar abgelehnt mit dem Hinweis auf die one-definition-rule (Definitionen im Header nur mit Zusatz extern, was diese (in den meisten Fällen) zur Deklaration werden lässt).
Interessanterweise würde gcc/ld das bei der aktuellen Einstellung problemlos "schlucken". Dies ist offenbar ein "Feature" von gcc/ld (wohl der Linker), das es problemlos ermöglichen würde, nicht-initialiserte globale Variablen im Header zu definieren (nicht initialisieren), ohne dass es hierbei zu praktischen Problemen (error, warning) kommt.
Nur zur Klarstellung der Begriffe:
Deklaration: extern int a;
Definition: int a;
Initialisierung: int a=5;Frage: Wie geht ihr "praktisch" damit um?
Setzt ihr Compiler-/Linker-Flags, die dieses Definieren im Header verhindern, oder nutzt ihr dieses Feature von gcc/ld?
-
Das ist nicht Dein Ernst, gell?
-
@volkard: sag uns einfach schonungslos die Wahrheit.
Möglichst mit klarer Quellenangabe.Warum lässt gcc/ld dies problemlos zu?
-
Erhard Henkes schrieb:
@volkard: sag uns einfach schonungslos die Wahrheit.
Möglichst mit klarer Quellenangabe.Deine Problembeschreibung reicht doch aus. Es ist ein "Feature", das zufällig in dieser Version geht, wie ist es mit der nächsten? Ihr werden kotzen, wenn Ihr beginnt, Sachen in shared objects auszulagern. Auf einmal sind es dann doch mehrere Objekte .Ich sehe nicht den Hauch einen Anlasses, Variablendefinitionen in headers zu packen. Wer sowas macht, der frißt auch kleine Kinder.
-
OK, klare Stellungnahme. Gibt es dazu auch eine klare Anweisung in C99?
Bleibt die praktische Frage:
Warum lässt gcc/ld solche "Untaten" problemlos zu? (in welchen Versionen das genau möglich ist, habe ich nicht recherchiert, gehe aber davon aus, dass dies kein Bug ist, sondern ein Feature, also gewollt!)
-
Vielleicht ist das was http://www.eggheadcafe.com/software/aspnet/35702858/tentative-definition.aspx
Oder wenigstens ein Suchanfang.
-
Wir haben das jetzt per Compiler- und Linker-Schalter abgesichert:
GCCFLAGS= -fno-common LDFLAGS= --warn-common
Damit befindet sich in kernel.map nun alles in bss.
COMMON sieht nun so aus:
*(COMMON) 0x000796c4 __kernel_end = . 0x000796c4 __end = .
Volkard Henkel ist übrigens bekannt duch sein hervorragendes und wirklich lesenwertes C++-Tutorial: http://www2.fh-augsburg.de/informatik/vorlesungen/XX/c_cplus/tutorial/henkel/
-
Erhard Henkes schrieb:
Interessanterweise würde gcc/ld das bei der aktuellen Einstellung problemlos "schlucken". Dies ist offenbar ein "Feature" von gcc/ld...
Welche Version von gcc macht so was? Was geben "gcc --version" und "ld --version" aus?
-
gcc Version 4.4.0
ld Version 2.19.1
-
Das ist überhaupt kein "Feature" von gcc oder ld. Man kann sich mit dem cpp (C-Präprozessor) den Code anschauen, so wie gcc den Code sieht... Header Dateien werden ja in den Quellcode "eingefügt", genauso wie Defines und Makros im Quellcode ersetzt werden...
-
Es gibt da noch ein Thema:
return; aus Funktionen vom Ergebnis-Typ void. MrX ist dafür, ich eher dagegen, weil mir ein return ohne Value nicht geheuer vorkommt. GCC schluckt. Kann man das auch mittels Schalter verbieten?
-
einfaches return; muss meines Erachtens jeder Compiler schlucken.
-
Jo, das ist ganz normales und korrektes C.
-
Es gibt ein Tool, um den Quellcode auf sauberes C zu prüfen, wie ich hier http://www.c-plusplus.net/forum/viewtopic-var-t-is-252326-and-start-is-60.html schon mal gepostet habe (das mit splint)...
-
Das prüft auch nur im Rahmen dessen, was die Macher von Splint für sauber halten
-
Mr X schrieb:
Das prüft auch nur im Rahmen dessen, was die Macher von Splint für sauber halten
Das ist nur ein Hilfswerkzeug. Der Compiler überprüft ja schon einiges und man kann splint zur Kontrolle benutzen, rein informativ. z.B. oder einfach nur "zur Kenntnisnahme".
Einfach mal drüberlaufen lassen und sich über die Tausende Warnungen wundern
-
Tausende Warnungen
Wer benötigt denn so etwas?
-
Erhard Henkes schrieb:
Tausende Warnungen
Wer benötigt denn so etwas?
Wer sichergehen möchte, dass der "Ring 0" Code "sauber" ist
-
weil mir ein return ohne Value nicht geheuer vorkommt
Tolle Begruendung ... ein einfaches return bei Funktionen ohne Rueckgabewert ist legitim. Bei Funktionen mit Rueckgabewert hat man halt
return "value"
und wenn nur eine void-Funktion, der Rueckgabewert also gestrichen ist, so kann auch der Rueckgabewert bei return gestrichen werden. Es ist ein bequemes Mittel eine Funktion vorzeitig zu verlassen, genau wie bei Funktionen mit Wertrueckgabe.
-
ein einfaches return bei Funktionen ohne Rueckgabewert ist legitim
ja, das ist richtig.