Hallo, was passiert genau, wenn man Header Files einbindet, die man gar nicht benötigt. Wird der compilierte Code größer oder wird nur die Compilierzeit größer? Was kann sonst noch passieren?
Ein #include ist so, als ob du den Inhalt der Headerdatei an dieser Stelle in den Code einfügst, mit allen Konsequenzen. Die Compilierzeit nimmt auf jeden Fall zu. Bei unsauber programmierter SW (bspw Leute, die Variablen in Headerdateien anlegen) nimmt auch die Codegröße zu und es kann zu Compilerfehlern kommen usw. (nicht nur) Meine Faustregel ist, in Headerdateien gehört nichts, was am Ende Platz benötigt. Außerdem sollte jede Headerdatei so gut es geht eigenständig sein - In headerdateien möglichst nicht andere includieren. Auf die Weise hat man überhaupt keine Probleme damit, auch wenn man Headerdateien einbindet die man nicht braucht.
Nehmen wir mal an ganz "normale" Header Files. Also Funktionsprototypen und vielleicht "extern" Variablen mit zugehörigem C-File.
Phantomix Ximotnahp schrieb: > Außerdem sollte jede Headerdatei so gut es geht eigenständig sein - In > headerdateien möglichst nicht andere includieren. "Leider" bleibt einem aber oft nichts anderes übrig als zig andere Header zu includieren um Typdefinitionen zu bekommen wie zB <stdint.h>. Das macht aber nichts. Hans schrieb: > Nehmen wir mal an ganz "normale" Header Files. Also Funktionsprototypen > und vielleicht "extern" Variablen mit zugehörigem C-File. Das erhöht nur die Compilezeit.
Externe Variablen müssen irgendwo existieren. Sie belegen also entweder Speicherplatz oder führen zu einem Abbruch beim Linken. Der Speicherplatz ist dann allerdings nicht im Header-File definiert, sondern in der "externen" Datei - das kann ja jede beliebige andere c oder h Datei im Projekt sein. Gleiches gilt für Funktionen. Bei Funktionen bin ich nicht sicher, was passiert, wenn man eine Funktion deklariert, sie nicht verwendet und nicht definiert. Ich schätze, das führt ebenfalls zu einem Abbruch des Linkers. Sicher bin ich allerdings, dass der Linker normalerweise alle nicht benutzten Funktionen entfernt. Sie existieren im compilierten programm gar nicht. Manche Header Dateien definieren globale Variablen, z.B. um den Status von irgend etwas anzuzeigen. Diese belegen auf jeden Fall Speicher, auch wenn sie nicht benutzt werden. Es passiert sehr leicht, den Zugriff auf solche Variablen falsch zu machen, vor allem in Interruptroutinen und Multi-Threaded Programmen. Deswegen würde ich sowas lassen. Wenn Du z.B. eine SD-Karten Library hast, die anzeigen soll, ob eine Karte eingesteckt ist und ob sie bereit ist, dann mach das nicht über eine von überall aus erreichbare globale Variable sondern stelle eine Funktion zur Verfügung, die den Wert der Variablen liefert. Nur die Funktion soll außerhalb der Library erreichbar sein. Das kostet zwar etwas Code und Performance, vermeidet aber Fehler durch Falsche Anwendung.
Stefan us schrieb: > Externe Variablen müssen irgendwo existieren. Sie belegen also > entweder > Speicherplatz oder führen zu einem Abbruch beim Linken. Nur wenn man sie verwendet. > Funktionen bin ich nicht sicher, was passiert, wenn man eine Funktion > deklariert, sie nicht verwendet und nicht definiert. Ich schätze, das > führt ebenfalls zu einem Abbruch des Linkers. Ja, die berühmten "undefined reference" Fehler die hier 3x täglich aufschlagen. > Sicher bin ich allerdings, dass der Linker normalerweise alle nicht > benutzten Funktionen entfernt. Sie existieren im compilierten programm > gar nicht. Nein. Beim GCC z.B. nur wenn man mit "-ffunction-sections" compiliert&linkt und mit "-Wl,--gc-sections" linkt. > Manche Header Dateien definieren globale Variablen, z.B. um den Status > von irgend etwas anzuzeigen. Diese belegen auf jeden Fall Speicher, auch > wenn sie nicht benutzt werden. Es sei denn man lässt unbenutzte Variablen mit "-fdata-sections" & "-Wl,--gc-sections" wegoptimierten (GCC). Variablen in Headern zu definieren (d.h. ohne extern) ist onehin sinnlos, weil dann für jede .c Dateie eine eigene angelegt wird und man nicht auf die der anderen Dateien zugreifen kann.
Dr. Sommer schrieb: > Stefan us schrieb: >> Externe Variablen müssen irgendwo existieren. Sie belegen also >> entweder >> Speicherplatz oder führen zu einem Abbruch beim Linken. > Nur wenn man sie verwendet. >> Funktionen bin ich nicht sicher, was passiert, wenn man eine Funktion >> deklariert, sie nicht verwendet und nicht definiert. Ich schätze, das >> führt ebenfalls zu einem Abbruch des Linkers. > Ja, die berühmten "undefined reference" Fehler die hier 3x täglich > aufschlagen. Achtung: Er sagte "sie nicht verwendet". In dem Fall passiert gar nichts. Deklarieren darf man eine Funktion so oft und so viel man will. Auch wenn sie nicht existiert. Solange sie nicht verwendet wird, ist das dem Linker piep-egal. Eine Funktionsdeklaration interessiert ja nur den Compiler, damit er evetuelle Aufrufe prüfen kann. Gibt es keinen Aufruf, interessiert die Deklaration niemanden weiter.
Karl Heinz schrieb: > Achtung: > Er sagte "sie nicht verwendet". > In dem Fall passiert gar nichts. Oh. Brille putz
@Dr. Sommer Ich habe inzwischen mal die von Dir empfohlene Compiler (bzw Linker) Option "-Wl,--gc-sections" ausprobiert. Diese hat auf mein Projekt (Webserver) aber überhaupt keinen Einfluss, es kommt exakt das gleiche binary heraus. Nun ist es so, dass meine Quelltexte keine unnötigen Funktionen enthalten. Insofern ist dies als das erwartete Ergebnis. Aber eines ist mir in diesem Zusammenhang noch unklar: Ich binde einige Standard Libraries ein, die zahlreiche unbenutzte Funktionen enthalten. Sie blähen mein Binary anscheinend dennoch nicht unnötig auf. Sehe ich es richtig, dass der Compiler/Linker unbenutzte Funktionen aus den Standard Libraries automatisch entfernt - auch ohne diese Option?
Stefan us schrieb: > Sehe ich es richtig, dass der Compiler/Linker unbenutzte Funktionen aus > den Standard Libraries automatisch entfernt - auch ohne diese Option? Anders rum. Er holt sich nur das, was er braucht. Was aber im Endeffekt aufs gleiche rausläuft. Diese gcc-Linker Option brauchst du ja auch nur deswegen, weil dieser Linker Object-Files als ganzes einbindet, ohne sich um die Aufteilung in Funktionen zu kümmern. Andere Linker machen das anders. Würdest du beim gcc-Linker von vorne herein jede Funktion in ein eigens C-File stecken und getrennt compilieren, hätte das daher den gleichen Effekt, wie diese Option.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.