Forum: Compiler & IDEs globales Array und Speicherbelegung


von Ron (Gast)


Lesenswert?

Vermutlich ist es ein lächerliches Anfängerproblem (AVRGCC und ATmega8):
Ich habe ein globales eindimensionales array aus uint8_t in dem ich 
Zeichen ablegen will. Irgendwie habe ich den Verdacht, daß der Inhalt 
des arrays (und eines weiteren, lokalen) von irgendwo sinnfrei verändert 
wird. ganz so als würde da eine andere Variable im gleichen 
Speicherbereich liegen.

Das erste: warum bekomme ich bei volatile die Warnung "warning: passing 
arg 1 of `strncmp' discards qualifiers from pointer target type" etc.

Dann: Wieso wird der nach dem compilieren angezeigte Speicherplatzbedarf 
nicht verändert, wenn ich das array größer dimensioniere? Wie kann ich 
dann wissen, wie groß mein belegter Speicher ist, denn ich gehe ganz eng 
an das limit:
AVR Memory Usage:
-----------------
Device: atmega8

Program:    7984 bytes (97.5% Full)
(.text + .data + .bootloader)

Data:        782 bytes (76.4% Full)
(.data + .bss + .noinit)


Ist irgendwas falsch daran, global
uint8_t  buffer[200]
zu schreiben und dann lokal
buffer[x]='a'
oder so zu machen?

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

> Das erste: warum bekomme ich bei volatile die Warnung "warning: passing
> arg 1 of `strncmp' discards qualifiers from pointer target type" etc.
Wahrscheinlich wird char* erwartet und ein pointer auf unsigned 
char/uint8_t uebergeben.

> Dann: Wieso wird der nach dem compilieren angezeigte Speicherplatzbedarf
> nicht verändert, wenn ich das array größer dimensioniere? Wie kann ich
> dann wissen, wie groß mein belegter Speicher ist, denn ich gehe ganz eng
> an das limit:
> ...
> Ist irgendwas falsch daran, global
> uint8_t  buffer[200]
> zu schreiben und dann lokal
> buffer[x]='a'
> oder so zu machen?
Nachgeschaut, ob buffer mglw. wegoptimiert wird, da vielleicht nie 
daraus gelesen wird? (Würde ich als bekennender lss/Disassembly Leser 
darin suchen). Im Zweifel könnte man volatile uint8_t test; 
test=buffer[0]; ausprobieren.

von Torsten L. (bluehorn)


Lesenswert?

Ron wrote:
> Das erste: warum bekomme ich bei volatile die Warnung "warning: passing
> arg 1 of `strncmp' discards qualifiers from pointer target type" etc.

Weil strncmp für "normale" char Arrays/Pointer definiert ist. Für 
volatile müsste man eigentlich eine eigene strncmp-Routine schreiben. 
Dadurch, dass Du das normale strncmp benutzt, umgehst Du ja die 
spezielle Codeerzeugung, die der Compiler sonst für volatile macht.

> Dann: Wieso wird der nach dem compilieren angezeigte Speicherplatzbedarf
> nicht verändert, wenn ich das array größer dimensioniere? Wie kann ich
> dann wissen, wie groß mein belegter Speicher ist, denn ich gehe ganz eng
> an das limit:

Tja, keine Ahnung, sollte eigentlich nicht passieren. Trivialprogramm 
hier:
1
char buf[7000];
2
3
int main(void) { return 0; }

Liefert bei mir (laut avr-size):
1
torsten@pulsar:~$ avr-gcc t.c
2
torsten@pulsar:~$ avr-size a.out
3
   text    data     bss     dec     hex filename
4
    100       0    7000    7100    1bbc a.out

Ist natürlich nicht Win-AVR, k.A., welches Tool da für diese 
Grössenangabe verwendet wird.

Also: Mach daraus mal ein Trivialbeispiel, damit wir das 
reproduzieren/wiederlegen können.

Gruss aus Dresden, Torsten

von OliverSo (Gast)


Lesenswert?

avr-size liefert auch unter WinAVR richtige Werte. Wenn sich die Größe 
des data-segments (da drin wird buffer als globale Variable angelegt) 
nicht ändert, stimmt was anderes nicht.
Schau mal ins map-file, ob dein buffer drin auftaucht, und wie groß das 
Feld dort ist.

Und zeig mal deinen Code. Wenn du neben den globalen Variablen auch noch 
große lokale Variablenfelder anlegst, gibt es Probleme.

Oliver

von Ron (Gast)


Lesenswert?

OK, wenn ich aber da kein volatile bei einer globalen Variable angebe, 
kann es ja sein, daß in einer Funktion Mist bei raus kommt.

Spielt es eigentlich irgendeine Rolle, ob ich
unsigned char oder uint8_t benutze?

Ich habe das Trivialprogramm erstellt und es liefert das erwartete 
Ergebnis: Die Data Speicherbelegung ändert sich - also bin ich (noch) 
nicht ganz Meschugge.
Aber! Bei meinem eigentlichen Programm passiert das nur, wenn ich bei 
der globalen Variable die Größe ändere. Das habe ich wohl irgendwie bei 
meinen bisherigen Tests übersehen. Es ändert sich aber nicht die Data 
Speicherbelegung bei einem lokal in einer Funktion angelegtem array. 
Auch nicht, wenn ich es mit ={0, ...} initialisiere :-(

von OliverSo (Gast)


Lesenswert?

>Es ändert sich aber nicht die Data
>Speicherbelegung bei einem lokal in einer Funktion angelegtem array.
>Auch nicht, wenn ich es mit ={0, ...} initialisiere :-(

Je nun, da die zur Laufzeit angelegt werden, weiss avr-size nichts 
davon. Und damit dürfte auch dein Problem erklärt sein - der Stack läuft 
über.

Oliver

von Ron (Gast)


Lesenswert?

>Schau mal ins map-file, ob dein buffer drin auftaucht, und wie groß das
>Feld dort ist.

Wow. Was für eine schicke Datei. Noch nie reingeschaut. Aber ja, da ist 
mein buffer und dahinter steht 0xc8. Also genau meine 200.

>Wenn du neben den globalen Variablen auch noch
>große lokale Variablenfelder anlegst, gibt es Probleme.

Wieso ist das so? Soll ich die lokalen großen (ab wann ist etwas groß?) 
arrays dann lieber auch globalisieren?

von Karl H. (kbuchegg)


Lesenswert?

Ron wrote:
>>Schau mal ins map-file, ob dein buffer drin auftaucht, und wie groß das
>>Feld dort ist.
>
> Wow. Was für eine schicke Datei. Noch nie reingeschaut. Aber ja, da ist
> mein buffer und dahinter steht 0xc8. Also genau meine 200.
>
>>Wenn du neben den globalen Variablen auch noch
>>große lokale Variablenfelder anlegst, gibt es Probleme.
>
> Wieso ist das so? Soll ich die lokalen großen (ab wann ist etwas groß?)
> arrays dann lieber auch globalisieren?

Ein zweischneidiges Schwert.
Auf der einen Seite hast du mit globalen Variablen den Vorteil,
dass dir der Linker die exakte verbrauchte Speichermenge dieser
Variablen ausrechnen kann und dich vor Überlauf warnen kann.
Auf der anderen Seite ist aber die dynamische Speicherauslastung
mit funktionslokalen Variablen besser, da sich mehrere Variablen
denselben Speicher teilen können. Dafür weiß wiederum niemand
im Vorfeld wieviel Speicher insgesamt verbraucht wird, weil das
ja auch von der Schachtelung der Funktionsaufrufe abhängt.

von OliverSo (Gast)


Lesenswert?

Wobei

>Data:        782 bytes (76.4% Full)
>(.data + .bss + .noinit)

mal gerade noch 254 byte SRAM für Stack (und lokale Variablen) lässt. Je 
nachdem, wieviele lokal in einer Funktion angelegten arrays und 
Variablen jetzt noch dazukommen, reicht das, oder auch nicht.

>Irgendwie habe ich den Verdacht, daß der Inhalt
>des arrays (und eines weiteren, lokalen) von irgendwo sinnfrei verändert
>wird. ganz so als würde da eine andere Variable im gleichen
>Speicherbereich liegen.

Das ist normalerweise ein untrügliches Zeichen dafür, das es nicht 
reicht.

Oliver

von Karl H. (kbuchegg)


Lesenswert?

OliverSo wrote:

>>Irgendwie habe ich den Verdacht, daß der Inhalt
>>des arrays (und eines weiteren, lokalen) von irgendwo sinnfrei verändert
>>wird. ganz so als würde da eine andere Variable im gleichen
>>Speicherbereich liegen.
>
> Das ist normalerweise ein untrügliches Zeichen dafür, das es nicht
> reicht.

Könnte natürlich auch ein Out-of-bounds Zugriff in einem Array sein.

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.