www.mikrocontroller.net

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


Autor: Ralf Rosenkranz (voltax)
Datum:

Bewertung
0 lesenswert
nicht 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







Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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.


Autor: Ralf Rosenkranz (voltax)
Datum:

Bewertung
0 lesenswert
nicht 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



Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...
{
   SB sb;
   SB_init (&sb, buf, len);
   return itoa (sb.sblen, buf, 10);
}

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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nee doch nicht. Habe Argumente verwexelt ;-)

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

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

  

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ralf Rosenkranz (voltax)
Datum:

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

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

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ralf Rosenkranz (voltax)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.