mikrocontroller.net

Forum: Compiler & IDEs globales Array und Speicherbelegung


Autor: Ron (Gast)
Datum:

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

Autor: Martin Thomas (mthomas) (Moderator) Benutzerseite
Datum:

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

Autor: Torsten Landschoff (bluehorn)
Datum:

Bewertung
0 lesenswert
nicht 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:
char buf[7000];

int main(void) { return 0; }

Liefert bei mir (laut avr-size):
torsten@pulsar:~$ avr-gcc t.c
torsten@pulsar:~$ avr-size a.out
   text    data     bss     dec     hex filename
    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

Autor: OliverSo (Gast)
Datum:

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

Autor: Ron (Gast)
Datum:

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

Autor: OliverSo (Gast)
Datum:

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

Autor: Ron (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

Autor: OliverSo (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

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.