Forum: Compiler & IDEs Variable als static deklarieren


von W.Müller (Gast)


Lesenswert?

Hallo zusammen,

ich deklariere innerhalb einer Funktion die Variable val_dyn als static:

void rot_decode (uint8_t)
{ uint8_t t_flag = 0;
  static uint8_t val_dyn;
       usw.

Diese Funktion wird von einer ISR aufgerufen, verändert aber keine 
Variable;
Optimierung im Makefile = 0 (sicherheitshalber (?)).
Benutzt werden WINAVR und avr-libc 1.4.3 sowie VMLAB zur Simulation.

Was passiert?
Übersetzung ok. ohne Fehlermeldungen und Warnungen; die Funktion 
arbeitet
einwandfrei, allerdings: val_dyn existiert nicht.

Beim Debuggen im 'single step' wird die Deklaration einfach 
übersprungen.

Kann mir jemand auf die Sprünge helfen? Was mache ich falsch?

(Hoffentlich habe ich die Situation ausreichend klar beschrieben).

Wolf

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Eine Definition erzeugt ja auch keinen ausführbaren Code, folglich
kann man da nicht im single step hinein.

Wenn du die Variable innerhalb der Funktion nirgends benutzt, wird
der Optimierer sie glücklich ignorieren -- sie kann ja nie geändert
oder gelesen werden.

von W.Müller (Gast)


Lesenswert?

Hallo Jörg,

ich hätte schreiben sollen "deklariert und definiert ...".

Natürlich wird die Variable innerhalb dieser Funktion benutzt, ich 
wollte nicht den Code der ganzen Funktion posten.
Also: val_dyn speichert einen über I2C-Bus gelesenen Wert bis zu einem 
erneuten Aufruf der Funktion.

Gruss

Wolf

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Vielleicht weiß VMLAB ja nicht, wie es diese Variable anzeigen soll,
keine Ahnung.  Existieren muss sie ja, wenn du da was abspeicherst.

von W.Müller (Gast)


Lesenswert?

Jede andere Variable lässt sich in VMLAB anzeigen.
AVR Studio verhält sich übrigens genau so wie in meinem ersten Beitrag 
beschrieben.

Was vermutest Du als Ursache?

von Uhu U. (uhu)


Lesenswert?

Das wird wohl ein kleines Problem/Defizit des Debuggers sein. Statische 
Variable liegen ja nicht auf dem Stack, sondern im Datensegment. 
Eventuell kannst du sie sehen, wenn der Debugger eine Möglichkeit 
bietet, globale Variablen anzusehen. Der Name könnte dann aber entweder 
kryptisch oder sonstwie eindeutig gemacht sein, denn es können ja viele 
Funktionen existieren, die dieselbe statische Deklaration enthalten - 
die muß jeweils mit einer anderen Speicheradresse verknüpft sein.

Die lokale Gültigkeit von lokalen statischen Variablen wird einzig durch 
den Compiler erzwungen. Wenn man die Adresse so einer Variablen kennt, 
kann man sie jederzeit zugreifen - auch wenn sie lexikalisch gerade 
nicht gültig ist.

Bei dynamischen Variablen ist das ausgeschlossen, da dynamische 
Variablen nur existieren, wenn ein Stackframe der Funktion existiert, in 
der sie definiert sind - ist die Funktion rekursiv, dann können sogar 
mehrere Frames vorhanden sein, für jede Inkarnation eins.

Sieh dir mal das map-Listing des Linkers an. Dort müßten die Namen und 
Adressen aufgeführt sein.

von W.Müller (Gast)


Lesenswert?

Danke für den Tipp.

<Das wird wohl ein kleines Problem/Defizit des Debuggers sein.>

Verwende ich AVR Studio statt VMLBab, ändert sich nichts!?

Im map-file finde ich:
  63:switches.c    **** uint8_t dg_flag = 0, t_flag = 0, temp;
 131                 .LM1-rot_decode
 132                 .LM1:
 133 0018 1B82          std Y+3,__zero_reg__
 134 001a 1A82          std Y+2,__zero_reg__

  64:switches.c    **** static uint8_t val_dyn; 
//enthält Wert der 1. Abfrage
  65:switches.c    ****

  66:switches.c    **** #define DG1_cw    0x81;
  67:switches.c    **** #define DG1_ccw  0x82;
  68:switches.c    **** #define DG2_cw    0x84;
  69:switches.c    **** #define DG2_ccw  0x88;
  70:switches.c    ****
  71:switches.c    ****   GICR &= ~(_BV(INT1));

Wenn ich das richtig interpretiere, existiert val_dyn nicht!!

Hier nochmals der Code (soweit relevant):

void rot_decode (uint8_t dg_stat[])
{

uint8_t dg_flag = 0, t_flag = 0, temp;
static uint8_t val_dyn; 
//enthält Wert der 1. Abfrage

#define DG1_cw    0x81;
#define DG1_ccw          0x82;
#define DG2_cw    0x84;
#define DG2_ccw          0x88;

  GICR &= ~(_BV(INT1));
....
....
  i2c_start(ENC_ADR + I2C_WRITE);    //IO-Expander abfragen
  temp = i2c_readNak();              //enthält Wert nach 1. Abfrage
  PAUSE_p(5);               //Prellzeit abwarten 
i2c_start(ENC_ADR + I2C_WRITE);    //IO-Expander erneut abfragen
        val_dyn = i2c_readNak();           //enthält gültigen Wert 
(dyn.)          i2c_stop();

(die letzten 6 Zeilen nur zum Verständnis)

von Uhu U. (uhu)


Lesenswert?

Da val_dyn in den ASM-Fragmenten, die du gepostet hast, nicht
zugegriffen wird, sieht man nichts davon. Die Deklaration bewirkt nur,
daß der Compiler irdendwo im Datensegment den Platz dafür reserviert.
Dafür wird zur Laufzeit kein Code ausgeführt.

Such mal im ASM-Output des Compilers nach einer Stelle, an der val_dyn
gelesen, oder geschrieben wird. Dann kennst du den Namen, den der
Compiler dafür generiert hat. Damit kannst du dann evtl. auch im
Debugger darauf zugreifen.

> Im map-file finde ich:

Das ist nicht der map-File, sondern das ASM-Listing des Compilers.

Unter dem map-Listing versteht man eine Liste der Zuordnungen von 
Symbolnamen zu Speicheradressen. Es wird nicht vom Compiler erzeugt, 
sondern vom Linker.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Guck besser in die Symboltabelle (Ausgabe von avr-nm, wird bei neueren
WinAVR-Makefiles automatisch erzeugt).

von Wolf (Gast)


Lesenswert?

Finde nach 'Build' die Warnung
static variable adress beyond RAM limit:val_dyn ->.0x800331

Auch für statische Variable in anderen Funktionen erscheinen 
entsprechende Warnungen. Hatte ich bisher nicht beachtet ( :( ).

Was kann die Ursache hierfür sein und wie könnte eine Abhilfe aussehen?

Im map-File erscheint val_dyn mit Adresse 0x0080032e.

Wolf

von Karl H. (kbuchegg)


Lesenswert?

Wolf wrote:
> Finde nach 'Build' die Warnung
> static variable adress beyond RAM limit:val_dyn ->.0x800331

Das klingt aber sehr danach, dass dein Speicher voll ist.

von Wolf (Gast)


Lesenswert?

Leider ist das wohl nicht der Grund: Atmega32, Flash 7700 words, also 
ca. 50% voll.

von Uhu U. (uhu)


Lesenswert?

Gibst du den richtigen Prozessortyp an?

von Karl H. (kbuchegg)


Lesenswert?

Wolf wrote:
> Leider ist das wohl nicht der Grund: Atmega32, Flash 7700 words, also
> ca. 50% voll.

Der Flash ist nicht das Problem.
Oder willst du deine Variablen nur auslesen?

Der SRAM ist das Problem.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> Leider ist das wohl nicht der Grund: Atmega32, Flash 7700 words,
> also ca. 50% voll.

Das ist nicht der Speicher, in dem statische Variablen abgelegt werden. 
Die landen im RAM, und davon hat der Mega32 deutlich weniger ...

von Wolf (Gast)


Lesenswert?

kbuchegg wrote:
>Der Flash ist nicht das Problem.
>Oder willst du deine Variablen nur auslesen?

Sollte mir eigentlich klar sein, sonst brauchte man ja wohl keine 
Variablen.

Speicherverbrauch lt. AVR Studio
   Data: 791 bytes (38.6% full)
   (.data + .bss +.noinit)


uhu wrote:
>Gibst du den richtigen Prozessortyp an?

ja, Atmega32

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Sieht aber so aus, als würde dein VMLAB nichts davon wissen.  Diese
Ausschrift sieht nicht nach Compiler oder Linker aus.

von Wolf (Gast)


Lesenswert?

Jörg wrote:

>Sieht aber so aus, als würde dein VMLAB nichts davon wissen.

Mag sein, die 'Ignoranz' bezüglich der staischen Variablen zeigt auch 
AVR Studio.
Welche Gründe dafür könnte es geben? Speicherbelegung für Daten und 
Programm scheiden m.E aus.

>Diese Ausschrift sieht nicht nach Compiler oder Linker aus.

Was meinst Du damit?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wolf wrote:

>>Diese Ausschrift sieht nicht nach Compiler oder Linker aus.
>
> Was meinst Du damit?

Das hier:

static variable adress beyond RAM limit:val_dyn ->.0x800331

Das sieht mir eher wie eine Meldung von VMLAB aus.

von Uhu U. (uhu)


Lesenswert?

> Ausschrift

Ist das deine Wortschöpfung?

von Florian (Gast)


Lesenswert?

Wenn der Code vollständig war (oben) und Deine statische Variable nur 
beschrieben und sonst nicht weiter verwendet wird, dann wird diese ggf. 
- zu Recht - wegoptimiert.

von Wolf (Gast)


Lesenswert?

Jörg wrote:

>static variable adress beyond RAM limit:val_dyn ->.0x800331

>Das sieht mir eher wie eine Meldung von VMLAB aus.

Stimmt; allerdings verwendet VMLAB den GNU C compiler genau so wie AVR 
Studio auch.

Da sich bisher für mich keine Alternativen zeigen: Gibt es die 
Möglichkeit, der statischen Variablen 'zwangsweise' eine Adresse im RAM 
zuzuweisen (ich möchte sie möglichst nicht global deklarieren)?


Florian wrote:

>Wenn der Code vollständig war (oben) und Deine statische Variable nur
>beschrieben und sonst nicht weiter verwendet wird, dann wird diese ggf.
>- zu Recht - wegoptimiert.

Würde ich ja verstehen, aber sie wird geschrieben und gelesen (s.u.):

    i2c_start(ENC_ADR + I2C_WRITE);    //IO-Expander abfragen
    temp = i2c_readNak();              //enthält Wert nach 1. Abfrage
    PAUSE_p(5);                        //Prellzeit abwarten
    i2c_start(ENC_ADR + I2C_WRITE);    //IO-Expander erneut abfragen
>>  val_dyn = i2c_readNak();           //enthält gültigen Wert
    i2c_stop();

Im weiteren Verlauf wird sie auch gelesen, z.B.
    if (val_dyn & 0x020)

BTW: Danke für die bisherige Hilfe.

Wolf

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wolf wrote:

>>Das sieht mir eher wie eine Meldung von VMLAB aus.

> Stimmt; allerdings verwendet VMLAB den GNU C compiler genau so wie
> AVR Studio auch.

Trotzdem ist die Meldung von VMLAB, nicht vom Compiler oder Linker.
VMLAB hat in der Analyse der Objektdatei festgestellt, dass die
Variable auf deinem Zielprozessor gar nicht im RAM untergebracht
worden ist.

> Da sich bisher für mich keine Alternativen zeigen: Gibt es die
> Möglichkeit, der statischen Variablen 'zwangsweise' eine Adresse im
> RAM zuzuweisen (ich möchte sie möglichst nicht global deklarieren)?

Das hilft doch nichts.  Du hast einfach keinen RAM mehr, zumindest
laut Meinung von VMLAB.  Offenbar geht hier VMLAB von einem anderen
Controller aus als der Compiler, oder es hat einen Bug und ist der
Meinung, der benutzte Controller hätte weniger RAM als er wirklich
hat.

von krono (Gast)


Lesenswert?

vieleicht hilft es, die variable mit einem vernünftigen Wert zu 
initialisieren.:
1
void rot_decode (uint8_t)
2
{ uint8_t t_flag = 0;
3
  static uint8_t val_dyn = 0;
      usw.

keine angst, per C-Standard wird diese Initialisiereung genau einmal 
ausgeführt und nicht
für jeden Aufruf.

HTH
      -krono

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

krono wrote:

> keine angst, per C-Standard wird diese Initialisiereung genau einmal
> ausgeführt und nicht
> für jeden Aufruf.

Quatsch.  Die Initialisierung einer lokalen Variablen wird bei
jedem Aufruf vorgenommen, und statische Variablen werden per C-Standard
ohnehin mit 0 initialisiert, wenn nichts anderes angegeben ist.

von krono (Gast)


Lesenswert?

Jörg Wunsch wrote:

>> keine angst, per C-Standard wird diese Initialisiereung genau einmal
>> ausgeführt und nicht
>> für jeden Aufruf.
>
> Quatsch.  Die Initialisierung einer lokalen Variablen wird bei
> jedem Aufruf vorgenommen, und statische Variablen werden per C-Standard
> ohnehin mit 0 initialisiert, wenn nichts anderes angegeben ist.

einer lokalen variable ja.
aber nicht bei einer statischen lokalen variable.
ansonsten wuerde dass hier nicht funktionieren.

(btw: c89 heisst, das ganze wird mit einem ANSI-C Compiler gebaut)
1
Script started on Sat Sep 22 17:19:30 2007
2
tppb:/tmp tobias$ cat static.c
1
#include <stdio.h>
2
3
void foo(void)
4
{
5
    static int var = 42;
6
    printf("%d\n", var++);
7
}
8
9
10
int main(void)
11
{
12
    foo();
13
    foo();
14
    foo();
15
    foo();
16
    return 0;
17
}
1
tppb:/tmp tobias$  c89 -o static static.c 
2
tppb:/tmp tobias$ ./static 
3
42
4
43
5
44
6
45
7
tppb:/tmp tobias$ exit
8
9
Script done on Sat Sep 22 17:20:08 2007

hth,
      -krono

von Uhu U. (uhu)


Lesenswert?

krono wrote:
> einer lokalen variable ja.
> aber nicht bei einer statischen lokalen variable.
> ansonsten wuerde dass hier nicht funktionieren.

Eine lokale statische C-Variable wird nur einmal bei Programmstart 
initialisiert. (C++ initialisiert sie, wenn sie zum ersten mal sichtbar 
wird.)

Die Eigenschaft 'lokal' wird bei statischen Variablen nur vom 
Scopemechanismus des Compilers erzwungen. Die Variable selbst lebt von 
Programmstart bis zum Ende, ist aber nur in dem Block sichtbar, in dem 
sie definiert ist.

von krono (Gast)


Lesenswert?

Uhu Uhuhu wrote:

> Eine lokale statische C-Variable wird nur einmal bei Programmstart
> initialisiert. (C++ initialisiert sie, wenn sie zum ersten mal sichtbar
> wird.)
>
> Die Eigenschaft 'lokal' wird bei statischen Variablen nur vom
> Scopemechanismus des Compilers erzwungen. Die Variable selbst lebt von
> Programmstart bis zum Ende, ist aber nur in dem Block sichtbar, in dem
> sie definiert ist.

hab ich nicht bezweifelt.
(selfquote)
keine angst, per C-Standard wird diese Initialisiereung genau einmal
ausgeführt und nicht
für jeden Aufruf.
(/selfquote)
genau ein mal. beim "betreten" von main.

von Uhu U. (uhu)


Lesenswert?

> genau ein mal. beim "betreten" von main.

Nein, das wird erledigt, bevor main aufgerufen wird - häufig schon vom 
Linker...

von krono (Gast)


Lesenswert?

nagut.. dann halt so ^^.

mein punkt war halt das einmalige intialisieren dieser variablen,
die ja (für ungeübte) nach lokaler variable aussieht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

krono wrote:

> mein punkt war halt das einmalige intialisieren dieser variablen,
> die ja (für ungeübte) nach lokaler variable aussieht.

Und mein Punkt war, dass du deine Aussage ,,wird nur einmal erledigt''
unter ein Stück Code mit zwei verschiedenen Initialisierungen
gesetzt hast, von denen eine wirklich nur einmal erfolgt, die andere
aber (automatische Variable) bei jedem Funktionseintritt.  Zudem war
die Initialisierung, auf die sich der Kommentar bezog (nämlich die
der statischen Variablen) völlig überflüssig, da sie der ohnehin
vom Compiler/Laufzeitsystem bereits vorgenommenen Initialisierung
aller statischer Objekte auf 0 entspricht.

Damit ist auch klar, dass dein Vorschlag, die Variable ,,mit einem
vernünftigen Wert zu initialisieren'', dem OP keinerlei Änderung
des Verhaltens bringen wird.  Der damit generierte Objektcode ist
nämlich letztendlich identisch.  (GCC erkennt mittlerweile, dass
eine Initialisierung eines statischen Objekts mit 0 bzw. NULL der
default-Initialisierung entspricht, und schiebt dadurch die Variable
nicht mehr aus dem .bss ins .data, wie er das früher noch gemacht
hat.)

von krono (Gast)


Lesenswert?

das mit den 2 deklarationen kam daher, dass ich nur den "vorgegebenen" 
code geaendert habe.

und die initialisierung statischer variablen auf 0 war mir bis dato 
nicht bekannt.

ist ja auch eigentlich fuers problem irrelevant.
ich wurde mich fragen, ob dass ueberhaupt hülfe.

von Uhu U. (uhu)


Lesenswert?

Noch so einer, der immer das letzte Wort haben muß, auch wenn er nichts 
zu sagen hat...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

krono wrote:

> und die initialisierung statischer variablen auf 0 war mir bis dato
> nicht bekannt.

Hmm, und das, wo du doch selbst mit dem C-Standard herumgewedelt
hast. ;-)  Tjaja, das steht auch alles im Standard... (wenn du's
nicht glaubst, popele ich dir auch gern noch die Kapitelnummer
dafür raus).

von Wolf (Gast)


Lesenswert?

krono wrote:

> vieleicht hilft es, die Variable mit einem vernünftigen Wert zu
> initialisieren.:

Habe ich ich schon früher versucht, erwartungsgemäss ohne Erfolg.

Nach wie vor bleibt für mich die zentrale Frage, wie ich AVR Studio 
(WINAVR) dazu bewege, meinen Code mit (lokalen) statischen Variablen zu 
compilieren und zu linken, um ihn mit STK500 zu testen.

Eine globale Deklaration möchte ich vermeiden; jedes bessere C-Handbuch 
weist darauf hin.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Moment mal, mit dem STK500 sollte bitteschön alles funktionieren, sonst
hast du noch ein ganz anderes Problem.  Bislang hattest du lediglich
geschildert, dass es in der Simulation von VMLAB nicht funktioniert
hat, selbst von AVR Studio war keine Rede.

von Wolf (Gast)


Lesenswert?

inzwischen hat sich zu diesem Thema vielerlei angesammelt, vielleicht 
hast Du es übersehen - meine Beiträge v. 29.8.07 und 1.9.07.
STK500 ist für mich eine komfortable Hw-Plattform mit einiger Peripherie 
wie LEDs, Schalter, UART und hat m.E. nichts mit den geschilderten 
Schwierigkeiten zu tun.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Fang einfach nochmal von vorn an, das ist alles zu verwirrend.

Was geht, was geht nicht, welche Fehlermeldungen, an welcher Stelle
tauchen die Fehlermeldungen auf?

Das da oben passt alles nicht mehr wirklich zusammen.

von Wolf (Gast)


Lesenswert?

Da ich meinen Code inzwischen verändert/erweitert habe, muss ich 
versuchen, den damaligen Stand zu restaurieren, werde mich aber auf 
WinAVR, AVRStudio (und STK500) beschränken und VMLAB zunächst ausser 
acht lassen.

Bis dahin Dank für bisherige Hilfe.

Wolf

von Wolf (Gast)


Lesenswert?

wegen anderer Prioritäten habe ich erst jetzt das Problem wieder 
aufgreifen können.

Ergebnis: Mit AVRStudio und STK500 als Target wird eine Variable als 
static ohne Probleme akzeptiert und so behandelt wie erwartet.

VMLAB verarbeitet tatsächlich <static> nicht richtig.

Danke nochmals.

Wolf

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Das ist schade.  Da Enrique VMLAB auch nicht mehr weiter entwickeln
will (weil es kommerziell einfach nie wirklich gelaufen ist), wird
sich das wohl auch nicht mehr ändern lassen.

von Oliver (Gast)


Lesenswert?

>VMLAB verarbeitet tatsächlich <static> nicht richtig.

Lokale static-variablen lassen sich im watch-Fenster schon ansehen, 
allerdings nicht im scope der zugehörigen Funktion, sondern im scope von 
main.

Oliver

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
Noch kein Account? Hier anmelden.