Hallo, ich habe festgestellt, dass sich ein 40kb projekt mal eben auf 20k reduziert, wenn man Stufe 1,2,3 einschaltet. Das kann doch irgendwie nicht sein? Stellt sich die allgemeine Frage: Sollte man oder besser nicht? Was fängt man sich damit ein? Gruss, Christian
Zusammengefasst: Einschalten! -O2 dürfte in den meisten Fällen die geeignete Wahl sein. Fehler durch die Optimierung sind in praktisch allen Fällen Fehler im eigenen Code. Insbesondere die delay-Funktionen funktionieren nur mit Optimierung.
Und dran gewöhnen, dass der Codefluss bei Debuggen nicht so geradlinig ist, wie man ihn aufgeschrieben hat. Variablen, die der Programmierer für das Verständnis bzw. die Überschaubarkeit des Codes eingeführt hat, braucht der Compiler auch nicht zwangsläufig 1:1.
> ich habe festgestellt, dass sich ein 40kb projekt mal eben auf 20k > reduziert, wenn man Stufe 1,2,3 einschaltet. Das kann doch irgendwie > nicht sein? Warum nicht? Optimierung ist dazu da, um den Code ressourcensparender zu machen. Das ist hier der Fall. > Stellt sich die allgemeine Frage: Sollte man oder besser nicht? Warum nicht? > Was fängt man sich damit ein? ??
Als Ergänzung zu möglichen Problemen, wenn man die Optimierung vorher noch nie genutzt hat: ein "vergessenes" volatile (vgl. avr-libc FAQ#1) macht sich sehr wahrscheinlich erst bei eingeschalteter Optimierung durch Fehlerverhalten in der Anwendung bemerkbar. Aber wie von Jan M. schon angemerkt: die Ursache ist dabei unzulänglicher Anwendercode (=etwas "vergessen") und nicht der Compiler, denn der macht was ihm aufgetragen wurde: möglicht gut optimieren, also u.a. Speicherzugriffe vermeiden und in Registern "cachen".
Hallo, wo wir beim Thema optimieren sind: Wie kann ich nach Fertigstellung eines Projektes mit dem ARM7 herausfinden, wieviel Stack tatsächlich genutzt wird? Bei mir stehen beim Linker die Werte standardmässig eingestellt, denke jedoch, dass man durch passgenaues Setzen mehr Speicher freimachen kann.
> Wie kann ich nach Fertigstellung eines Projektes mit dem ARM7 > herausfinden, wieviel Stack tatsächlich genutzt wird? Genaue, aber schwierige Methode: Anhand des generierten Assemblercodes herausfinden, wann das Programm wieviel Bytes Daten auf den Stack schiebt bzw. in Form lokaler Variablen nutzt. Dann durch eine Analyse des Programmflusses (verschachtelte Funktionsaufrufe) herausfinden, wann der Stack maximal benutzt wird. Dann die Stacknutzung zu diesem Zeitpunkt abzählen. Einfache, aber ungenaue Methode: Stack zunächst großzügig dimensionieren. Beim Programmstart den gesamten Stackbereich mit "magic Numbers" füllen. Programm längere Zeit laufen lassen, dabei darauf achten, dass möglichst alle Verzweigungen des Programmflusses auch tatsächlich auftreten (auch innerhalb von Bibliotheksfunktionen). Dann die Bytes auf dem Stack, die nicht mehr die magic Number enthalten, abzählen. Es kann leider nicht immer garantiert werden, dass während des Programmlaufs auch tatsächlich der stackmäßige worst Case eintritt.
Leute, knausert nicht mit dem Stack rum! Stack-Overflows gehört zu den ekelhaftesten und am schwersten zu findenden Problemen. Sie treten im übrigen meist erst nach Ende der DEBUG-Phase auf. Ein Beispiel zu dem Thema: Vor vielen Jahren wurde in Hamburg ein neues Stellwerk in Betrieb genommen. Die Software dieses Stellwerks fiel durch Stack-Overflow alle paar Tage mal aus, meist im Berufsverkehr. Das Ganze ging so weit, daß das Stellwerk ausgeschaltet und durch den Vorgänger ersetzt wurde. Erst Monate später war der Stack-Overflow gefunden, und das neue Stellwerk ging erneut in Betrieb. Bernhard
@ Bernhard R. (barnyhh) >Leute, knausert nicht mit dem Stack rum! Stack-Overflows gehört zu den >ekelhaftesten und am schwersten zu findenden Problemen. Sie treten im Frage. Kann man nicht als Option eine Laufzeitprüfung des Stacks einbauen? Klar kostet das Performance, das ist aber in vielen Fällen unkritisch. Zu Debugzwecken ist es Gold wert. MfG Falk
Kann man. Wenn richtig erinnert, bietet der IAR-EWARM eine Option dafür. Beim GNU-compiler ist das auch vorgesehen (mapcs-stack-check, Limit in SL). Selbst aber noch nicht erfolgreich ausprobiert. Bin nichtmal wirklich sicher, ob die Funktionalität beim arm-gcc implementiert ist. Kommandozeilenparameter gibt es zwar, in der Dokumentation von 4.2.1 finde ich im Moment garnichts mehr dazu.
@ Falk Die Sache mit den Laufzeitprüfungen ist wunderschön und gut, aber ... - Der "Performancefetischismus" selbst vieler "professioneller Software-Entwickler" (und ihrer Manager) läßt natürlich nicht zu, daß Stackprüfungen im produktiven Einsatz der Software noch aktiv sind. - Nächstes Problem: Was soll der Processor denn noch machen, wenn der Stack "knallt"? Und gar noch im produktiven Einsatz? Derartige Probleme sollten bereits in der Architektur eines Systems durchdacht und gelöst sein. Stattdessen - meine Erfahrung in großen Projekten - orientierungsloses Nicht-Design. Das war die reale Welt der (Software-)Großindustrie schwarz in schwarz dargestellt. Bitte keine Kommentare - es kann nur noch besser werden. Bernhard
> - Der "Performancefetischismus" selbst vieler "professioneller > Software-Entwickler" (und ihrer Manager) läßt natürlich nicht zu, daß > Stackprüfungen im produktiven Einsatz der Software noch aktiv sind. Was würdest du von einem Auto halten, bei dem man ein ABS einbaut, den Firmeneigenen Testfahrer ein paar Runden drehen lässt, und dann das ABS wieder ausbaut bevor das Auto an den Endverbraucher geht? Mit der Begründung "wurde beim Testen ja auch nie gebraucht"... Frei nach meinem ehemaligen SoftEng-Prof zum Thema assert und #define NDEBUG ...
Die Eiffel-Leute bringen das Beispiel vom Schwimmer, der beim Training im Pool das Begleitboot dabei hat, bei der Ärmelkanal-Überquerung aber nicht. Aber ich wollte ja nichts weiter sagen. Bernhard
@ Bernhard R. (barnyhh) >Die Eiffel-Leute bringen das Beispiel vom Schwimmer, der beim Training >im Pool das Begleitboot dabei hat, bei der Ärmelkanal-Überquerung aber >nicht. Also sterben wie wahre Helden! MFG Falk
Sind ja ganz tolle Vergleiche. Nur mal so am Rande: Was soll das Programm bitte sinnvolles machen, wenn es feststellt, daß der Stack übergelaufen ist? Das ist so ähnlich wie die Checks des Rücgabewerts von malloc auf dem PC. Ist zwar nett, wenn man das überall einbaut, aber beim typischen PC-Programm ist der Rechner schon lange vorher so mit Auslagerung beschäftigt, daß der Benutzer inzwischen den Reset-Knopf gedrückt hat. Ein typisches GUI-Programm hat außerdem nicht mal die Chance, dem Benutzer noch ein Fenster anzuzeigen, ohne dabei Speicher allokieren zu müssen. Bei embedded-Software ist das natürlich etwas anders. Aber auch da kann ich mir beim Stack-Überlauf nur noch vorstellen, daß das Programm dann einen sauberen Reset durchführen kann, aber das war's dann auch schon.
>...Aber auch da kann ich mir beim Stack-Überlauf nur noch vorstellen, daß >das
Programm dann einen sauberen Reset durchführen kann, aber das war's >dann auch
schon.
.. und kommt irgendwann wieder an den Punkt.
MW
Das Ding könnte dann aber ein Crash-Log schreiben. Und man steht bei der Fehlersuche nicht ganz im dunkeln?! Wenn es keine 100% fehlerfreie Software gibt, dann sollte das Debugging eben nie aufhörren... Ist anwendungsabhängig. Windows mit Debugcode laufen zu lassen währe ja keine Freude... (speed...)
X. H. wrote:
> Das Ding könnte dann aber ein Crash-Log schreiben.
In den EEPROM?
Ich stelle mir gerade vor, wie aus deinem rechten Rückspiegel ein
Crash-Log rausgewackelt kommt, weil der Microcontroller da drin
einen unerwarteten Fehler hatte... ;-)
Ja, in einen Speicher meine ich. Denn der Log ist für eine Person, die den Fehler beheben soll. Bei diesem Stellwerk hätte man vielleicht dadurch den Fehler schneller gefunden.
Junge. Wenn dir der Stack überläuft, dann kannst du im Regelfall gar nichts mehr machen. 1) merkst du den Stacküberlauf in deinem Programm erst wenn es bereits zu spät ist. Viel zu spät 2) Abhängig vom Programm, kann ein Stack-Overflow so ziemlich alles bewirken. Mit dem gezielten Aufruf eines Crash-Log aus dem man auch noch irgendwas ermitteln kann, ist es dann normalerwiese nichts mehr. Auf einem Desktopsystem kann man davon ausgehen, dass das Betriebssystem noch Speicher vorrätig hat, um weiter arbeiten zu können. Auf einem µC ist das aber nicht. Wenn der Stack in die Variablen reinläuft, bzw. umgekehrt man sich mit Variablenzugriffen den Stack zerschiest, dann musst du schon froh sein, wenn dein µC nicht einfach Amok läuft und noch halbwegs geordnet weitermacht.
>nicht einfach Amok läuft und noch halbwegs geordnet weitermacht.
Deshalb werden bei mir alle Controller verlötet! :-)
MW
Wer ordentlich programmiert, der bekommt auch keine Stackprobleme. Es geht ja nicht so sehr um Endlosrekursionen, sondern eher um die lokalen Arrays, deren Grenzen nicht beachtet werden.
Leute, programmiert eure Mikrocontroller in Fortran! Bis Fortran-77 gab's weder Rekursion noch dynamische Speicherverwal- tung noch sonst irgendetwas, was den Speicherverbrauch zur Laufzeit zum Lotteriespiel werden lässt. Durch die fehlende Rekursion konnte alles, aber auch wirklich alles in statisch reservierten Speicher gelegt werden, selbst die Rücksprungadressen von Unterprogrammauf- rufen. Ein Stack ist damit nicht erforderlich, und der Speicherverbrauch steht schon zur Compilezeit exakt fest. Wenn der Speicher zu knapp ist, wird das spätestens beim Programmstart erkannt. Fazit: Zuverlässige Mikrocontrollerprogramme sind nur in Fortran möglich! Nun mal Scherz beiseite: Wäre es möglich, das F77-Frontend des GCC mit dem AVR-Backend zu kombinieren? Vielleicht müsste man eine an den AVR angepasste Laufzeitbibliothek schreiben. Aber dann sollte es doch möglich sein, auch Fortran auf dem AVR zu machen, oder?
yalu wrote: > Fazit: Zuverlässige Mikrocontrollerprogramme sind nur in Fortran > möglich! Schon mal was von Occam gehört? Diese Sprache war eigens für Embedded System konzipiert worden und hatte auch die Eigenheit, den gesamten Speicherverbrauch statisch rechnen zu können. Nur hatten die Transputer, für die INMOS das gemacht hat, keine Interrupts im üblichen Sinn, sondern Prozesse, die von Ereignissen getriggert wurden (Prozessverwaltung war in Hardware). Damit war INMOS fein raus, der Speicherverbrauch deterministisch, verschachtelte priorisierte Interrupts allerdings schwierig, denn es gab insgesamt nur 2 Prozessprioritäten.
yalu wrote: > Ein Stack ist damit nicht erforderlich, und der Speicherverbrauch > steht schon zur Compilezeit exakt fest. Wenn der Speicher zu knapp > ist, wird das spätestens beim Programmstart erkannt. Genau, und du kaufst einen doppelt so großen Controller, weil du für alles 5000 Elemente reservieren musst, obwohl du im Normalfall nur 50 brauchst. ;-) Im Ernst: wer statisch bekannte Probleme dynamisch löst, dem ist nicht zu helfen. Es gibt aber auch Probleme, bei denen die Daten nicht in vorhersagbarer Menge anfallen und bei denen es darauf ankommt, im Rahmen der möglichen Ressourcen einfach das Maximum herauszuholen. > Nun mal Scherz beiseite: Wäre es möglich, das F77-Frontend des GCC mit > dem AVR-Backend zu kombinieren? Es scheitert zumindest erstmal daran, dass FORTRAN zwingend einen 64-bit-FP-Support braucht, damit man die libf77 compilieren kann.
@yalu: > Nun mal Scherz beiseite: Wäre es möglich, das F77-Frontend des GCC mit > dem AVR-Backend zu kombinieren? Vielleicht müsste man eine an den AVR > angepasste Laufzeitbibliothek schreiben. Aber dann sollte es doch > möglich sein, auch Fortran auf dem AVR zu machen, oder? Die sind schon "verheiratet", aber wg. den fehlenden Bibliotheken wird der AVR-F77 wohl bei den üblichen Binärdistributionen nicht mitgeliefert. => selber die GCC-Quelltexte übersetzen, da kannst du das Fortran-Frontend einfach einschalten. Bei mir hat sich z.B. der avr-gcj (Java-Compiler) mitinstalliert, mangels libgcj für den AVR jedoch nicht verwendbar. Freiwillige?
Andreas Kaiser schrieb: > Schon mal was von Occam gehört? Natürlich, ich habe sogar mal etwas damit programmiert. Allerdings gerade einmal so viel, um nachzuweisen, dass eine Transputer- Schaltung, die ich damals entwickelt habe, funktioniert. Ein wenig mehr habe ich in Assembler gemacht. Irgenwie fand ich den Aufbau der Transputer-Befehle sehr pfiffig. Jörg Wunsch schrieb: > Es scheitert zumindest erstmal daran, dass FORTRAN zwingend einen > 64-bit-FP-Support braucht, damit man die libf77 compilieren kann. Naja, wenn man Fortran ernsthaft auf µC benutzen wollte (ich persönlich will zwar, nur der Ernst dazu fehlt noch etwas ;-)), würde man wahrscheinlich sowieso die libF77 durch etwas handlicheres, vergleichbar mit der AVR-Libc, ersetzen. Ernst Bachmann schrieb: > Die sind schon "verheiratet", aber wg. den fehlenden Bibliotheken > wird der AVR-F77 wohl bei den üblichen Binärdistributionen nicht > mitgeliefert. Darauf wird es wohl hinauslaufen, dass man bibliotheksmäßig etwas Neues stricken muss. Mal schauen, wenn ich irgendwann demnächst einen Mußetag habe (was leider nicht wahrscheinlich ist), könnte ich mal versuchen, eine minimalistsiche Laufzeitbibliothek anzufangen, nur so als Proof-of-Concept ;-)
yalu wrote:
> Irgenwie fand ich den Aufbau der Transputer-Befehle sehr pfiffig.
Aber nur wenn man damit Occam realisieren wollte, denn dafür und nur
dafür war der Befehlssatz vorgesehen. In C sah das weniger schön aus,
Ausdrücke wie (++i != 10) oder ?: wurden etwas umständlich.
Und das hier skizzierte Stack-Problem war grad da in C besonders
perfide. Weil man die Stacks aller zig Prozesse schon gern im schnellen
internen RAM haben wollte, aber das genau war bei 2KB kaum möglich ohne
jeden Prozess bytegenau auszurechnen.
Dummerweise ist eben die Trennung zwischen reinen Sprachelementen und Bibliothek bei FORTRAN nicht so strikt wie bei C. Dadurch brauchst du letztlich eine Bibliothek, um den Compiler überhaupt benutzen zu können. Allerdings habe ich mittlerweile Schwierigkeiten, ein "Hello, world!" in FORTRAN zu zimmern, insofern ist mein Interesse an einem derartigen Compiler eher marginal. Interessanter fände ich (neben Ada, was ja offenbar bereits ganz gut in die Gänge gekommen ist) dann eher noch Pascal.
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.