Ich bastel aktuell an einem AVR-GCC Projekt das so langsam aus den
Nähten quillt - mehrere eingebundene (Quelltext-) Bibliotheken,
funktional hat sich im Laufe der Bearbeitung auch vieles geändert. Wie
durch ein Wunder funktioniert das Ganze, obwohl ich eigentlich längst
den Überblick verloren hab, welcher Code noch wirklich dazu gehört und
welche Teile der Quelltexte nur noch "toter Ballast" sind.
Gibts eigentlich einen formalen Ansatz, um ungenutzte Funktionen sowie
globale Variablen in einem komplexen C Projekt zu identifizieren? Ich
würde den Code gern "verschlanken", insbesondere auch die Bibliotheken
auf den tatsächlich genutzen Umfang zurechtstutzen.
Micha schrieb:> Gibts eigentlich einen formalen Ansatz, um ungenutzte Funktionen sowie> globale Variablen in einem komplexen C Projekt zu identifizieren?
Compiler warnungen als errors behandeln lassen, und auf pedantic
stellen, dann sagt der schon welche Variablen nicht benutzt werden.
Du kannst z.B. auch mal Doxygen über das Projekt laufen lassen.
Mit den Call- und Callergraphen bekommst du auch einen Überblick,
welche Funktionen von anderen Funktionen aufgerufen werden.
Zudem kannst du damit auch gleich die Dokumentation erstellen.
Also normalerweise bindet ein C compiler nicht genutzte Funktionen
garnicht ein. Was du mit ungenutzten Variablen wirklich sparen kannst
haelt sich in Grenzen. Wenn du noch RAM frei hast ist es total egal,
ansonsten nimm einen Chip mit mehr Speicher.
Salewski schrieb:> Takao K. schrieb:>> Also normalerweise bindet ein C compiler nicht genutzte Funktionen>> garnicht ein.>> Bei AVR-GCC ist das nicht so einfach>> http://www.mikrocontroller.net/articles/GCC:_unbenutzte_Funktionen_entfernenPIC32 benutzt gcc und wenn ich eine Funktion nicht verwende, ist der
erzeugte code kleiner, macht nichts, kann man einfach drinlassen. Das
ist ja die idee mit den .H dateien, also dass nur ein Prototyp
uebergeben wird, und die Funktion wird dann bei Bedarf hinzugelinkt.
Einfach mal ausprobieren, also eine lib die nur ein paar Funktionaufrufe
hat, diese auskommentieren. Sollte dann einige K weniger sein.
Also dass waere ja eine Katastrophe wenn man dass jedesmal manuell
machen muesste.
Salewski schrieb:> Takao K. schrieb:>> Also normalerweise bindet ein C compiler nicht genutzte Funktionen>> garnicht ein.>> Bei AVR-GCC ist das nicht so einfach>> http://www.mikrocontroller.net/articles/GCC:_unben...
Wenn ich das richtig interpretiert habe, war das nicht so einfach,
aber mittlerweile schon. Sehe ich das richtig?
> Die Standard-Linkerscripts aktueller GCC-Distributionen> (WinAVR, WinARM) sind bereits entsprechend angepasst.
Jeder anständige Editor bietet eine Suchfunktion über das ganze Projekt.
Schah halt nach, ob die fraglichen Funktionen irgend auftauchen.
Alternativ einfach mal auskommentieren. Compiler/Linker sagt dir dann
schon, wenn was fehlt.
Oliver
Takao K. schrieb:> Also normalerweise bindet ein C compiler nicht genutzte Funktionen> garnicht ein. Was du mit ungenutzten Variablen wirklich sparen kannst> haelt sich in Grenzen. Wenn du noch RAM frei hast ist es total egal,> ansonsten nimm einen Chip mit mehr Speicher.
Der C Compiler bindet nicht, das macht der Linker.
Der Compiler packt alles aus einem c file in ein object file. Der Linker
bindet die einzelnen oject files zu einem. Da ist alles drin!
Einen Unterschied gibt es bei den Libs. Aus einer lib holt der Linker
nur, was auch aufgerufen wird.
Takao K. schrieb:> Was du mit ungenutzten Variablen wirklich sparen kannst> haelt sich in Grenzen. Wenn du noch RAM frei hast ist es total egal,> ansonsten nimm einen Chip mit mehr Speicher.
Dem TO geht es doch gar nicht darum speicher auf dem mC einzusparen. Der
TO will sein Projekt aufräumen (Code entfernen der nicht mehr verwendet
wird) um es wieder übersichtlicher zu machen, nicht weil der mC zu klein
ist.
Taktiken zum Aufräumen:
A. wegwerfen und neu machen.
Man weiß ja jetzt was man wirklich wollte und hat es schon einmal
gemacht, kann es deshalb normalerweise besser
B. Das entsorgen was man nie anfasst und nie braucht.
Man löscht immer mehr und dann fehlt einem Minuten später irgendwas ganz
wichtiges.
C. Das zusammenfassen was man braucht und Ordnen.
Meistens hält man viel zu viel für wichtig und behält dann doch zu viel.
Auswahl der Richtigen Methode? Mach dir einen Plan ob nun auf Papier,
mit Doxygen oder wenn man kann im Kopf ist egal.
Modularisieren: Das was zusammen gehört, gehört auch zusammen gelagert.
Abstrahieren: Dinge die die gleicht Funktion erfüllen nur einmal
aufbewahren.
Versionskontrolle (git, svn) benutzen und oft einchecken, so kann man
nach nachvollziehen was man gemacht hat und zu jedem Punkt zurück.
Wenn du aber selbst deine Werkstatt nie benutzt woher sollst du dann
wissen was wichtig ist und das nicht?
Nun kann man sich überlegen ob man "oben" oder "unten" anfängt, d.h. ob
man mit konkreten Funktionen anfängt "berechne nächste Vorhersage(int
a,...., float z)" oder "addiere(int a, int b)"
Robert N. schrieb:> A. wegwerfen und neu machen.
Er schreibt das nicht umsonst als ersten Vorschlag ;-)
Und beim 'neu machen' gleich mal darauf achten, dass man universell
einsetzbare Funktionen als Bibliotheksfunktion macht, also ein *.h mit
den Prototypen UND GANZ WICHTIG gescheite Doku dazu. Ein *.c enthaelt
dann den Code der Funktion, sofern die nicht so einfach ist, dass man
sie besser als inline static in der *.h implementiert.
Davor steht eigentlich die Festlegung deiner eigenen Regeln. Wie werden
Funktionen genannt? Init_I2C() oder I2C_Init() ?
Wie kommen die Parameter in der Reihenfolge?
Also ich verwende grob sowas:
Modul: fifo
=> Header = fifo.h
=> Funktionen heissen fifoXXX
=> mit erstem Parameter stets der Fifo,
=> Parameter links sind 'wichtiger' als die weiter rechts, d.h. der
nat"urliche Nachdenkprozess 'was brauch ich?' liefert sie in der
Reihenfolge in der sie geschrieben werden.
Die Idee dahinter ist - wenn man so ein schlechtes Gedaechtnis hat wie
ich - die eigenen Funktionsnamen, Datentypen und Dateinamen zu erraten
nachdem man sie vergessen hat ;-)
Aehmmmm, was wollte ich eigentlich sagen...?
Marc P. schrieb:> Robert N. schrieb:>> A. wegwerfen und neu machen.>> Er schreibt das nicht umsonst als ersten Vorschlag ;-)
Ist allerdings Unsinn. Es ist ganz normle Praxis beim Programmieren, ab
und zu mal seinen Code aufzuräumen, ohne immer gleich alles von ganz
vorne neu zu schreiben.
Oliver
Oliver S. schrieb:> Marc P. schrieb:>> Robert N. schrieb:>>> A. wegwerfen und neu machen.>>>> Er schreibt das nicht umsonst als ersten Vorschlag ;-)>> Ist allerdings Unsinn.
Nö ist es nicht. Schlage ich auch vor.
> Es ist ganz normle Praxis beim Programmieren, ab> und zu mal seinen Code aufzuräumen, ohne immer gleich alles von ganz> vorne neu zu schreiben.
Also unter aufräumen (kleine lokale Quellcodebaustelle) verstehe ich was
gänzlich anderes, als entmüllen (viel Müll im gesamten Quellcode und
kein Überblick mehr).