Ist 'static' für globale Variablen Pflicht?

#461294
Lesenswert?

Hallo,

ich starte noch mit AVRs, und zuerst entroste ich meine alten 
C-Kenntnisse. Als Übung portiere ich gerade einen kleinen 
Basic-Interpreter von vorher Java auf jetzt C (für den avr-gcc). Ich 
verwende AVRStudio4 und WinAVR (aktuelle Versionen), einen ATMega168 und 
den AVR-Dragon zum debuggen.

Dabei ist mir etwas komisches aufgefallen:

Eine meiner globalen Variablen (vom typ char [32], außerhalb aller 
Funktionen deklariert) wurde während des Programmlaufs teilweise 
überschrieben, und zwar sowohl im AVRDebugger als auch per DebugWire im 
Prozessor. Das passierte immer während eines bestimmten verschachtelten 
Funktionsaufrufs. Der Compiler war auf 'schwache Optimiering' 
eingestellt.

Wenn ich die Optimierung ganz ausschaltete, dann wurde nichts 
überschrieben, nur bei eingeschalteter Optimierung passierte das.

Erst nachdem ich die globale Variable zusätzlich als 'static' deklariert 
hatte, wurde sie gar nicht mehr überschrieben, also auch bei 
eingeschalteter Optimierung nicht.

Auch nicht überschreiben wurde sie, wenn ich den ATMega128 wählte, also 
mit und ohne Optimierung (aber den habe ich halt nicht real sondern nur 
als Debugger-Simulation).

Ich dachte ich schreibe das mal hier, eventuell hat noch jemand ein 
ähnliches Problem, und ein einfaches 'static' könnte helfen.

Oder ist das eventuell schon allgemein bekannt, und ich sollte besser 
meine Klappe halten ;)

soweit, Grüße Ralf






Gast #461302
Lesenswert?

Nein ist nicht Pflicht. Das wäre auch ein ziemlich grosser Klops!

Hast du die Variable in zwei oder mehr Quellcodedateien deklariert 
(angelegt)? Sie darf nur in einer Quellcodedatei deklariert werden; in 
den anderen Quellcodedateien wird sie nur als extern definiert.
Achte mal auf Linkerwarnungen bzw. schalte Linkerwarnungen ein.
#461321
Lesenswert?

@Stefan(1): der ganze Code ist nur in einer einzigen Datei.

@Stefan(2): jo, das SRAM ist schon mächtig voll, das könnte es sein. 
Mich wundert dann aber, dass ein 'static' das Problem behebt.

@Karl heinz Buchegger: kann gut sein. Ein anderes Problem macht die 
Fehlersuche aber etwas kompliziert: Mein Debugger im AVRStudio liefert 
für Funktionsparameter bei eingeschalteter Optimierung manchmal falsche 
Werte. Hier ein Codeschnipsel zu dem FalscheWerteProblem, bei dem das 
bei mir im Debugger so ist wie gesagt, siehe Kommentar hinter 'testFunc' 
(hat aber nix mit dem Topic des Threads zu tun):

<c>
#include <stdint.h>
#include <stdlib.h>

typedef size_t length_t;

typedef struct
{
   char* sbbuf;
   length_t sblen;
   length_t len;
} SB;

void SB_init (SB* sb, char* sbbuf, length_t len)
{
   sb->sbbuf = sbbuf;
   sb->sblen = len;
   sb->len = 0;
}

char* testFunc (char* buf, length_t len)
//--- Wenn Optimierung an ist (-s1), dann ---
//--- zeigt der AVRStudio4-Debugger hier ---
//--- für len einen falschen Wert an ---
{
   SB sb;
   SB_init (&sb, buf, len);
   return itoa (sb.sblen, buf, 10);
}

static char* result = 0;

int main (void)
{
   char buf [0x20];
   result = testFunc ((char*) &buf, 0x20);
   while (1==1);
   return 0;
}
</c>

Grüße Ralf


#461327
Lesenswert?

Da ist der AVR-GCC fehlerhaft:

Wenn die gleiche globale Variable in verschiedenen Objekten definiert 
ist, nimmt er stillschweigend an, daß sie auch dieselbe sein soll und 
überlagert sie alle.

Ich bin da auch schon mal drauf reingefallen.


Andere Compiler meckern dagegen und wollen es richtig gemacht haben:

Also die Variable gefälligst nur einmal definieren und dann per *.h-File 
als extern deklarieren.


Eine statische Variable existiert nur in einem Objekt und kann daher 
nicht überlagert werden.


Peter
Gast #461330
Lesenswert?

Nee doch nicht. Habe Argumente verwexelt ;-)

Aber hier knallt's
1
int main (void)
2
{
3
   char buf [0x20];
4
   result = testFunc ((char*) &buf, 0x20);
5
   while (1==1);
6
   return 0;
7
}

richtig:
1
int main (void)
2
{
3
   char buf [0x20];
4
   result = testFunc ((char*) buf, 0x20); // bzw. &buf[0]
5
   while (1==1);
6
   return 0;
7
}

  
#461337
Lesenswert?

> Aber hier knallt's
>
>
1
>    result = testFunc ((char*) &buf, 0x20);
2
>
>
> richtig:
>
>
1
>    result = testFunc ((char*) buf, 0x20); // bzw. &buf[0]
2
>

uff, ... da hast Du wahrscheinlich gerade auch mein erstes Problem 
gelöst. Denn die Konstruktion mit der falschen Adresse (oben) habe ich 
gleich einigemale im Programm.

Grüße Ralf
#461340
Lesenswert?

> Fehlersuche aber etwas kompliziert: Mein Debugger im AVRStudio liefert
> für Funktionsparameter bei eingeschalteter Optimierung manchmal falsche
> Werte.

Ich sehe was du meinst.

> //--- Wenn Optimierung an ist (-s1), dann ---
> //--- zeigt der AVRStudio4-Debugger hier ---
> //--- für len einen falschen Wert an ---

Es ist nicht ungewöhnlich, dass Debugger ausser Tritt
kommen, wenn Optimierungen eingeschaltet sind.

Der Debugger geht von einer Annahme aus:
Jedes Statement im Source Code macht genau das
was drauf steht.
Und dann kommt der Optimizer und dreht im Programm
alles mögliche um.

Konkret erwartet der Debugger das 2. Argument zu der
Funktion in den Registern R24:R25. Tatsächlich hat
der Optimizer aber dafür gesorgt, dass der 2te Parameter
in den Registern R22:R23 übergeben wird. Und damit zeigt
natürlich der Debugger was falsches an. Wenn du aber
das Pgm durchsteppst und am Ende der Funktion mal
die strcut SB sb untersuchst, stellst du fest dass ihre
Werte stimmen.

Moral -> Debugger und Optimizer vertragen sich nicht gut.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren