Ich stehe im Moment gerade etwas auf dem Schlauch ... Wenn ich mit dem Debugger in dem folgenden Code lande erzählt mir das Atmel Studio regNum wäre wegoptimiert und ich kann mir die Variable nicht anschauen. bool ReadRegisterCmd(uint8_t * regValue) { uint8_t regNum = uart_getc(); if( (regNum >=0) && (regNum <= 0x29) ) { return AD9854_ReadRegister(regNum, regValue); } return 0; } 1. Darf der Compiler das ? 2. Ich kenne von anderen Compilern, das im Debug Mode nichts optimiert wird.
Ja, er darf es. Und eherned Gesetz bei GCC ist, daß die Debig-Einstellungen keinen Einfluß auf den erzeugten Code haben dürfen.
Optimierung ausschalten ? Debugmodus bedeutet nur das die Zusatzinfos nicht entfernt werden bzw. überhaupt generiert werden.
Wenn Du sicher Variablen beim Debuggen ansehen willst, setze sie volatile. Vergiss aber hinterher nicht, dies wieder zu entfernen. Mit aktiver Optimierung wird es aber eh' schwierig zu debuggen.
Dankeschön an alle :) Gibt es bem Atmel Studio so etwas wie #define DEBUG, wenn die Debug Configuration ausgewählt ist, das man abfragen kann ?
Schalt die Optimierung aus wenn du Debuggen willst. Dafür muss man nun kein Konstrukt dafür bauen. Aber der Cimpiler liefert dir das Define zum abfragen
Stefan schrieb: > Schalt die Optimierung aus wenn du Debuggen willst. Dafür muss man nun > kein Konstrukt dafür bauen. > Aber der Cimpiler liefert dir das Define zum abfragen Dann ist ja gut ;) Das #define kann man halt im Code da einfügen wo man möchte, die globale Optimierung ein/aus ist da nicht so selektiv. Stell dir vor, du hast ein Programm, das ab und zu in einen Fehlerzustand läuft. Das ist es doch sinnvoll das Programm optimiert in Echtzeit laufen zu lassen bis der Debugger hardwaremässig feststellt, das eine bestimmte Programmadresse (Die Fehlerbehandlung Routine) erreicht wurde. Da willst du jetzt aber alle deine lokalen Variablen anschauen und nicht wegoptimiert haben. Und für Trace Ausgaben und Diagnose Meldungen benutz ich das immer wieder gerne. Man darf halt nicht nur einen 8 Bit Controller mit seinen beschränkten Resourcen betrachten. Und ich arbeite ja nicht nur mit GCC und mit AVRs. Aber in diesem einen Falle hätte es natürlich mit Aus/Einschaltung der Optimierung funktioniert.
Hans-Georg Lehnard schrieb: > Stell dir vor, du hast ein Programm, das ab und zu in einen > Fehlerzustand läuft. Das ist es doch sinnvoll das Programm optimiert in > Echtzeit laufen zu lassen bis ... Das ist generell immer ein Problem. Denn auf der einen Seite möchte man natürlich möglichst exakt das Programm im Debugger laufen sehen, dass auch in echte läuft. Auf der anderen Seite benötigt der Debugger natürlich auch Information, damit er möglichst dem Programmierer entgegen kommen kann und ihm die aus dem Programm rausgezogene Information in einer dem Programm angepassten Form präsentiert. > der Debugger hardwaremässig feststellt, > das eine bestimmte Programmadresse (Die Fehlerbehandlung Routine) > erreicht wurde. Da willst du jetzt aber alle deine lokalen Variablen > anschauen und nicht wegoptimiert haben. Na, ja. Ganz so ist es ja nicht. Der Wert existiert im laufenden Programm. Nur gibt es keine Speicherstelle in die er zwischendurch mal geparkt wird. Aber grundsätzlich muss ja der Wert, den die Funktion von uart_getc() kriegt, irgendwo sein. Wenn es keine Variable dafür gibt, dann lungert der in irgendeinem Register rum. Das wird auch immer wieder dasselbe Register sein. d.h. wenn dein Hardware-Debugger dir die Möglichkeit gibt, dir die Prozessor-Register anzusehen, dann wirst du dort in irgendeinem Register das Ergebnis des uart_getc wieder finden. Und es wird auch in jedem Programmlauf das immer gleiche Register sein. Unter Umständen muss man dann auch ein wenig den Assembler Code studieren, um rauszufinden welches Register das ist. Ein Debugger, der erst mal nur mit dem arbeitet, was ihm der Compiler an Informationen hinterlassen hat, wird da natürlich nicht fündig. Da muss man dann schon als Entwickler selbst ein wenig nachhelfen und darf sich nicht scheuen, auch mal in die tieferen Gefilde runterzusteigen.
Karl Heinz schrieb: > > Ein Debugger, der erst mal nur mit dem arbeitet, was ihm der Compiler an > Informationen hinterlassen hat, wird da natürlich nicht fündig. Da muss > man dann schon als Entwickler selbst ein wenig nachhelfen und darf sich > nicht scheuen, auch mal in die tieferen Gefilde runterzusteigen. Genau das wollte ich ja, dem Debugger die Information hinterlassen wo ich gerne die meine information zum Lesen hätte, damit ich nicht lange herumsuchen muss, aber der Compiler wollte nicht und hat es wegoptimiert. Das man irgendwann mal ganz tief unten suchen muss, keine Frage ...
Karl Heinz schrieb: > Und es wird auch in jedem > Programmlauf das immer gleiche Register sein. Unter Umständen muss man > dann auch ein wenig den Assembler Code studieren, um rauszufinden > welches Register das ist. Zumindest das Dwarf Debugging Format unterstützt verschiedene Arten von Adressierungen. Neben stack-relativ können auch Register angegeben werden. Wenn du also im Debugger dir die betreffende Variable ansehen willst kann es durchaus sein, dass der Wert der dir angezeigt wird nicht irgendwo vom Stack sondern aus einem Register gelesen wird. Für dich ist das völlig transparent. Du siehst dir einfach die Variable an, und brauchst eigentlich nicht zu wissen, wo diese nun genau im Speicher liegt. Wie gesagt, Dwarf bietet diese Möglichkeit. D.h. du kannst dir grundsätzlich auch "wegoptimierte" Variablen ansehen, denn wegoptimiert kann auch bedeuten dass der Wert lediglich in einem Register gehalten wird. Soweit die Theorie. Ob dein Compiler diese Information auch generiert bzw. dein Debugger sie auswerten kann, ich weiß es nicht.
lex schrieb: > Wie gesagt, Dwarf bietet diese Möglichkeit. > D.h. du kannst dir grundsätzlich auch "wegoptimierte" Variablen ansehen, > denn wegoptimiert kann auch bedeuten dass der Wert lediglich in einem > Register gehalten wird. > > Soweit die Theorie. Ob dein Compiler diese Information auch generiert > bzw. dein Debugger sie auswerten kann, ich weiß es nicht. Offenbar wird das von den Debuggern nicht unterstützt, denn gcc erzeugt entsprechende Infos selbst für Variablen, die wegoptimiert sind. Etwa:
1 | void fun (void) |
2 | {
|
3 | int bummer = 123; |
4 | }
|
5 | |
6 | int main() |
7 | {
|
8 | return 0; |
9 | }
|
und das übersetzen mit: $ avr-gcc foo.c -Os -g2 -save-temps -o foo.elf $ avr-readelf -w foo.elf Wie man im s-File sieht, ist die Variable wegoptimiert und die Funktion enhält nur noch ein RET, (Debug)-Labels und Kommentare:
1 | fun: |
2 | .LFB0: |
3 | .file 1 "foo.c" |
4 | .loc 1 2 0 |
5 | .cfi_startproc |
6 | /* prologue: function */ |
7 | /* frame size = 0 */ |
8 | /* stack size = 0 */ |
9 | .L__stack_usage = 0 |
10 | .LVL0: |
11 | ret |
12 | .cfi_endproc |
13 | .LFE0: |
14 | .size fun, .-fun |
In der readelf-Ausgabe hingegen steht unser bummer samt Wert und Typ:
1 | <2><3a>: Abbrev Number: 3 (DW_TAG_variable) |
2 | <3b> DW_AT_name : (indirect string, offset: 0x0): bummer |
3 | <3f> DW_AT_decl_file : 1 |
4 | <40> DW_AT_decl_line : 3 |
5 | <41> DW_AT_type : <0x47> |
6 | <45> DW_AT_const_value : 123 |
7 | <2><46>: Abbrev Number: 0 |
8 | <1><47>: Abbrev Number: 4 (DW_TAG_base_type) |
9 | <48> DW_AT_byte_size : 2 |
10 | <49> DW_AT_encoding : 5 (signed) |
11 | <4a> DW_AT_name : int |
Beim TO wird die lokale Variable benutzt. Daher ist davon auszugehen, dass sie nicht komplett wegoptmiert wurde, sondern in Registern gehalten wird. Mit ein paar besseren Optionen wäre die gesamte Funktion fun() weggefallen.
Eben. Ich trau mich wetten dass die Variable im Dwarf-Teil des .elf noch auftaucht, und zwar mit einem Register als Speicherort. Readelf würde da Klarheit bringen. Wenn der TO seine .elf anhängen würde könnte man das nachprüfen. Höchstwahrscheinlich wird der Atmel Debugger diese Information einfach nicht verwerten. Evtl. könnte man mit gdb eine Gegenprobe machen.
Wie alle Diskussion hier ist das mal wieder ein Selbstläufer, meine Fragen sind ja schon längst beantwortet ... Ich schiebe meine Variablen, die ich sehen will ins "Watch" Fenster und step durch mein Programm. Ich will nicht ein extra Kommandozeilentool (readelf) anwerfen um mir das Register zu suchen wo die Variable nun tatsächlich steht. Das ist mir einfach viel zu umständlich.
Das elf-File sollte nur Klarheit bringen, ob die Variable, wie im Betreff geschieben, wegoptimiert wurde (wie in Johanns Beispiel). Oder ob diese, wie eher zu vermuten ist, in Register abgelegt wurde.
Hans-Georg Lehnard schrieb: > Ich will nicht ein extra Kommandozeilentool (readelf) anwerfen um mir > das Register zu suchen wo die Variable nun tatsächlich steht. Das ist > mir einfach viel zu umständlich. ... was meinst du, wie dein GCC gestartet wird.
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.