Forum: Compiler & IDEs Ist 'static' für globale Variablen Pflicht?


von Ralf R. (voltax)


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







von Stefan (Gast)


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.

von Stefan (Gast)


Lesenswert?

Ahja - wie voll ist dein SRAM auf dem AVR? Rennt vielleicht schon der 
Stack im Variablenbereich Amok? Ein "bestimmter verschachtelter
Funktionsaufruf" hört sich danach an...

von Karl heinz B. (kbucheg)


Lesenswert?

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

Du hast irgendeinen anderen Fehler im Program.
Was du siehst, sind die Symptome und nicht die Ursache.


von Ralf R. (voltax)


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



von Stefan (Gast)


Lesenswert?

1
...
2
{
3
   SB sb;
4
   SB_init (&sb, buf, len);
5
   return itoa (sb.sblen, buf, 10);
6
}

Klassiker. Geht schief, weil sb nach dem return illegal wird.

von Peter D. (peda)


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

von Stefan (Gast)


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
}

  

von Stefan (Gast)


Lesenswert?

Tip: Sei geizig mit den Casts. Wenn der Compiler meckert hat es oft 
einen Grund. In diesem Falle hätte der Funktionsaufruf ohne (cahr*) Cast 
das Problem aufgedeckt.

von Ralf R. (voltax)


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

von Karl heinz B. (kbucheg)


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.

von Karl heinz B. (kbucheg)


Lesenswert?

> Aber hier knallt's

Macht für den gcc keinen Unterschied.
Der gcc ist schlau genug zu verstehen, was mit
der Adresse eines Arrays gemeint ist.
Die Datentypen stimmen nicht, daher die Warning.
Das Endergebnis sieht aber völlig gleich aus.

von Ralf R. (voltax)


Lesenswert?

@all

danke für die prompte Hilfe.

wenn ich mit meinem Basic-Interpreter-Dings wieder mal nicht 
weiterkomme, werde ich natürlich wieder hier bei Euch fragen, ... das 
habt Ihr jetzt davon ;))

Grüße Ralf

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


Lesenswert?

Peter Dannegger wrote:

> Da ist der AVR-GCC fehlerhaft:

Sei vorsichtig mit deinen Worten: dieses Verhalten ist ausdrücklich
vom Standard zugelassen.  Wenn du deine Klappe nicht hälst, such ich
mir die Stelle raus und werf damit nach dir. :-)

Kann man übrigens mit -fno-common ausschalten, wenn man das nicht
haben will.

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.