Hi, konsumiert eine Funktion auch Flashplazt, wenn diese definiert aber nie aufgerufen wird? Danke Sommer
Die sollte der Compiler schon wegoptimieren. Einfach mal ausprobieren: Die nicht benutze Funktion mitcompilieren und dann das Programm mit auskommentierter nicht benutzter Funktion compilieren. Es sollte das gleiche Ergebis (grösse des Compilats) herauskommen. Sonst ist der Compiler Mist. Das dürfte allerdings nicht für Interrupt-Service-Routinen gelten.
Ganz so einfach ist die Sache nicht. Wenn die Funktion static ist, dann ist es kein Problem, weil sie nur von der Übersetzungseinheit, in der sie definiert ist, aufgerufen werden kann und damit der Compiler problemlos feststellen kann, ob sie aufgerufen wird. Ist sie nicht static, dann hat der Compiler keine Wahl - er muß die Funktion liefern, denn sie könnte ja von einer anderen Übersetzungseinheit aus aufgerufen werden. Da kann also höchstens noch der Linker einspringen. Beim GNU-Linker ist es allerdings so, daß er einzelne Funktionen nicht entfernen kann, sondern nur ganze Übersetzungseinheiten. Wenn also die Funktion alleine oder nur mit anderen unbenutzten Funktionen zusammen in einem .c-File steckt, dann wird sie auch entfernt.
>aber nie aufgerufen
Die Aussage ist doch eindeutig, oder?
"Nie" bedeutet für mich, dass sie auch nicht aus irgendwelchen
Modulen heraus aufgerufen wird. (nur mal etwas "Korinthenkackerei" am
Rande. Also nichts für ungut!)
Ist es nicht aus so, dass Funktionen (z.B. aus der stdio-lib) nur dann
mit verwendet werden, wenn sie auch wirklich gebraucht werden?
Das ist dann aber die Aufgabe des Linkers, oder?
> Wenn also die Funktion alleine oder nur mit anderen > unbenutzten Funktionen zusammen in einem .c-File > steckt, dann wird sie auch entfernt. Aber auch nur dann, wenn das aus dem .c-File enstehende .o-File in eine Bibliothek verpackt und diese dem Linker übergeben wird. Wird das .o-File direkt dem Linker übergeben, bindet er es auf jeden Fall ein, auch wenn es nicht benötigt wird. So ist das zumindest beim ld aus den GNU binutils-2.16.1, der typischerweise zusammen mit GCC verwendet wird.
Der GCC/LD kann nicht benutzte Funktionen entfernen. Dazu verwendet man die Compilerflags "-ffunction-sections -fdata-sections" und das Linkerflag "--gc-sections". Beispiel-Makefile: http://www.mikrocontroller.net/trac/browser/trunk/Makefile
> "Nie" bedeutet für mich, dass sie auch nicht aus irgendwelchen > Modulen heraus aufgerufen wird. Klar. Aber der Compiler weiß das nicht. Er muß annehmen, daß die Funktion aufgerufen werden könnte, denn während er eine Übersetzungseinheit bearbeitet, hat er absolut keine Informationen über die anderen. Deshalb muß er die Funktion mitliefern, auch wenn sie in Wirklichkeit nicht aufgerufen wird (es sei denn, sie ist static, weil sie dann gar nicht von woanders aus aufgerufen werden kann). > Das ist dann aber die Aufgabe des Linkers, oder? Ja.
@Andreas Schwarz: Danke für den nützlichen Tip mit den sections-Optionen. Schon wieder was dazugelernt :)
Rolf Magnus schrieb: > (es sei denn, sie ist static, weil > sie dann gar nicht von woanders aus aufgerufen werden kann) Das ist aber irgendwie auch unlogisch - oder? Eine static Funktion wird nur innerhalb einer Funktion in der gleichen Quelle benutzt. Und ob diese andere Funktion benutzt wird, ist dann ja wieder unbekannt, sodass davon ausgegangen werden muss, dass sie gebraucht wird. (?)
Sourcecode schrieb: > Rolf Magnus schrieb: >> (es sei denn, sie ist static, weil >> sie dann gar nicht von woanders aus aufgerufen werden kann) > > Das ist aber irgendwie auch unlogisch - oder? Eine static Funktion wird > nur innerhalb einer Funktion in der gleichen Quelle benutzt. Es ging um Funktionen, die nicht benutzt werden. Wird eine static Funktion innerhalb einer Übersetzungseinheit nicht benutzt, dann kann sie der Compiler entfernen. Wie kann so etwas entstehen? Zb indem man 2 Funktionen wahlweise zur Verfügung stellt und mit einem Präprozessor Makro je nach Umfeld die eine oder die andere aufruft.
1 | static void foo1() |
2 | {
|
3 | ...
|
4 | }
|
5 | |
6 | static void foo2() |
7 | {
|
8 | ...
|
9 | }
|
10 | |
11 | void bar() |
12 | {
|
13 | #ifdef _MEGA16_
|
14 | foo1(); |
15 | #else
|
16 | foo2(); |
17 | }
|
Klar könnte man das auch anders lösen, indem man die Funktionen selber mit Präprozessoranweisungen auswählt, aber es ging ja um die Frage, wie so etwas entstehen KANN. > Und ob > diese andere Funktion benutzt wird, ist dann ja wieder unbekannt, sodass > davon ausgegangen werden muss, dass sie gebraucht wird. (?) Korrekt.
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.