Forum: Compiler & IDEs Array > 4


von boris (Gast)


Lesenswert?

Hallo Leute,
ich versuche ein globales Array anzulegen : "volatile unsigned char 
test[32]" Wenn ich diese Array im Watchwindow anzeige wird es auf 4 
Elemente beschränkt. Jedes Array größer 4 wird abgeschnitten. Egal ob 
global oder lokal angelegt. Kennt jemand dieses Problem? Kann es an 
einem Speichermodell liegen?
Ich arbeite mit AVR-Studio 3.53.

Vielen Dank
Gruß Boris

von Jonas (Gast)


Lesenswert?

hmm. kann eigentlich nur an avrstudio liegen. ich hatte schon größere 
arrays, die ham gefunzt (in der schaltung)... kann sein, dass das avrs 
die abschneidet.(?)

von Yalcin (Gast)


Lesenswert?

Hallo Boris,

nach fast zehn Jahren bin ich mit Eclipse 3.7.2, avr-gcc 4.5.3, atmega8 
und avrdude 5.11.1 auf das selbe Problem gestoßen.
Ich konnte den Fehler umgehen indem ich das Array nicht bei der 
deklaration initialisiere, sondern erst nach der deklaration.

Fehler: uint8_t array[] = {1, 2, 3, 4, 5, 6};

kein Fehler:
uint8_t array[6];
array[0] = 1;
array[1] = 2;
...

ich kann mir nicht erklären wieso dieser Fehler(ohne Fehlermeldung) 
auftritt da ich mich noch so gut wie gar nicht mit compilern auskenne 
und mein simulavr auch nicht laufen will.

Gruß und ein großes Dankeschön an die Mikrocontroller.net Community!!!
Yalcin

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Yalcin schrieb:
> Hallo Boris,
>
> nach fast zehn Jahren bin ich mit Eclipse 3.7.2, avr-gcc 4.5.3, atmega8
> und avrdude 5.11.1 auf das selbe Problem gestoßen.
> Ich konnte den Fehler umgehen indem ich das Array nicht bei der
> deklaration initialisiere, sondern erst nach der deklaration.
>
> Fehler: uint8_t array[] = {1, 2, 3, 4, 5, 6};
>
> kein Fehler:
> uint8_t array[6];
> array[0] = 1;
> array[1] = 2;
> ...

Die zweite Variante ist wesentlich ineffizienter als die erste.

Sollte man sowas verwenden, nur weil eine IDE zu dumm [tm] ist, das 
korrekt anzuzeigen?

> ich kann mir nicht erklären wieso dieser Fehler (ohne Fehlermeldung)

Das gibt keine Fehlermeldung weil es kein Fehler ist.

von Stefan E. (sternst)


Lesenswert?

Um was für einen "Fehler" geht es überhaupt?
Da Eclipse eine komplett andere IDE ist, kann es ja wohl kaum wirklich 
um den gleichen Fehler wie im 10 Jahren alten OP gehen.

von Rolf Magnus (Gast)


Lesenswert?

Johann L. schrieb:
> Die zweite Variante ist wesentlich ineffizienter als die erste.

Warum?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Für die erste Variante wird ein Literal angelegt, für die zweite nicht. 
Das gilt sowohl für auto Variablen als auch für solche im static 
Storage. Zumindest bei GCC.

von Yalcin (Gast)


Lesenswert?

Johann L. schrieb :
>Das gibt keine Fehlermeldung weil es kein Fehler ist.

Aber es ist doch eindeutig das wenn ich ein Array deklariere und 
initialisiere ich anschließend auf alle Elemente zugreifen können muss.
Wie gesagt funktioniert die gleiche Struktur mit einem Elemente(Array) 
<= 4.

Stefan Ernst schrieb:
>Da Eclipse eine komplett andere IDE ist, kann es ja wohl kaum wirklich
>um den gleichen Fehler wie im 10 Jahren alten OP gehen.

Das kann ich nicht mit sicherheit sagen aber der Tenor ist der gleiche.

Ich habe Tage verbracht diesen Fehler zu finden. Hoffe es kann 
behilflich sein.

Gruß Yalcin

von Karl H. (kbuchegg)


Lesenswert?

Yalcin schrieb:
> Johann L. schrieb :
>>Das gibt keine Fehlermeldung weil es kein Fehler ist.
>
> Aber es ist doch eindeutig das wenn ich ein Array deklariere und
> initialisiere ich anschließend auf alle Elemente zugreifen können muss.

> Wenn ich diese Array im Watchwindow anzeige wird es auf 4
> Elemente beschränkt.

rein aus C-Warte gesehen, ist nichts Falsches in deinem Code. Wenn es 
sich um ein Problem handelt, dass der Debugger irgendwas nicht anzeigen 
kann oder deine IDE da irgendwas abartiges macht, dann muss man in diese 
Richtung weitergehen. Aber aus C-Sicht gibt es keinen Grund, warum es da 
in einem laufenden C-Programm ein Problem geben sollte.

> ich kann mir nicht erklären wieso dieser Fehler(ohne Fehlermeldung)
> auftritt da ich mich noch so gut wie gar nicht mit compilern auskenne
> und mein simulavr auch nicht laufen will.

Da gibts deswegen keine Fehlermeldung, weil es sich auch um keinen 
Programmfehler handelt. Das ist irgendwas in deinem Debugger oder deiner 
IDE. irgendeine Einstellung (oder auch ein Bug, obwohl ich letzters 
nicht wirklich glaube)

Du musst unterscheiden zwischen Fehlern die du in dein Programm einbaust 
und Fehlern die in den von dir verwendeten Werkzeugen existieren.

von Rolf Magnus (Gast)


Lesenswert?

Johann L. schrieb:
> Für die erste Variante wird ein Literal angelegt, für die zweite nicht.

Ja, und? Variante 2 dürfte unter anderem deshalb eher deutlich schneller 
sein (ich würde mal überschlagsmäßig mit Faktor 2-3 rechnen), allerdings 
auch speicherintensiver.

von Yalu X. (yalu) (Moderator)


Lesenswert?

@boris:

Kannst du denn im Debugger einzelne Array-Elemente mit Index >= 4
anzeigen lassen, also bspw. array[4] oder array[31]?

Wenn ja: Werden die erwarteten Werte angezeigt?

Wenn ja: Dann handelt es sich wohl tatsächlich um ein reines
Anzeigeproblem im Debugger bzw. AVR-Studio.

von Stefan E. (sternst)


Lesenswert?

Yalcin schrieb:
> Aber es ist doch eindeutig das wenn ich ein Array deklariere und
> initialisiere ich anschließend auf alle Elemente zugreifen können muss.
> Wie gesagt funktioniert die gleiche Struktur mit einem Elemente(Array)
> <= 4.

"Funktioniert" in welcher Hinsicht? Reden wir hier wirklich von einem 
IDE/Debugger-Anzeige-Problem (wie im OP), oder vielleicht doch von einem 
Runtime-Problem (Programm funktioniert, oder funktioniert nicht)?

Wenn Letzteres, dann tippe ich auf ".data-Section nicht ins Hex-File 
exportiert".

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
> Johann L. schrieb:
>> Für die erste Variante wird ein Literal angelegt, für die zweite nicht.
>
> Ja, und? Variante 2 dürfte unter anderem deshalb eher deutlich schneller
> sein (ich würde mal überschlagsmäßig mit Faktor 2-3 rechnen), allerdings
> auch speicherintensiver.

Daß Variabte 2 ist für globale und statischen Variablen eben nicht 
wirklich schneller.  Grund: Variante 1 initialisiert zum init-Zeit vor 
main, während Variante 2 erst dann läuft, wenn die Anwendung bereits 
gestartet ist.  Ob es bis zu main ein paar µs länger dauert ist idR 
vollkommen Banane.

von Sam P. (Gast)


Lesenswert?

Vielleicht hat es was mit dem Umstand zu tun, dass die Größe des Arrays 
nicht explizit angegeben wurde. Das war ja mal eine GCC-eigene 
Erweiterung (inzwischen ist das in irgendeinem neueren C-Standard, 
IIRC).

Passiert das immer noch, wenn man sowas macht:
1
uint8_t array[6] = { 1, 2, 3, 4, 5, 6 };

Was übrigens die Effizienz angeht: Initialisierte Variablen werden vor 
dem Aufruf von main() in einer Schleife aus dem Flash initialisiert (ins 
RAM kopiert). Manuelle Initialisierung geschieht erst zu dem Zeitpunkt, 
zu dem man die Zeilen ausführt und kann sowohl mehr als auch weniger 
Flash-Bytes verbrauchen, je nach genauen Datentypen und Größe der 
Konstanten.

Automatische Initialisierung durch GCC verhindert versehentlichen 
Zugriff auch noch uninitialisierte Variablen (unbezahlbar!), spart 
Zeilen im Quelltext (auch wichtig!), ggf. Flash-Bytes (die paar sind 
nicht so wichtig), kostet aber Zeit bis zum Aufruf von main (meist 
vollkommen unwichtig -- wenn's sehr schnell losgehn muss, nimmt man 
einen Sleep-Modus).

Das Manuelle ist die Mühen also nicht wert. Nur wegen einem Bug im 
Debugger (welch Ironie!) sollte man sich seinen Quelltext nicht 
verunstalten.

von Yalcin (Gast)


Lesenswert?

Stefan Ernst schrieb:
>>Yalcin schrieb:
>> Aber es ist doch eindeutig das wenn ich ein Array deklariere und
>> initialisiere ich anschließend auf alle Elemente zugreifen können muss.
>> Wie gesagt funktioniert die gleiche Struktur mit einem Elemente(Array)
>> <= 4.

>"Funktioniert" in welcher Hinsicht? Reden wir hier wirklich von einem
>IDE/Debugger-Anzeige-Problem (wie im OP), oder vielleicht doch von einem
>Runtime-Problem (Programm funktioniert, oder funktioniert nicht)?
>
>Wenn Letzteres, dann tippe ich auf ".data-Section nicht ins Hex-File
>exportiert".

Ich gehe auch davon aus das -ich nenne es meinen nicht erfüllten Willen- 
an der .data-Section liegt. Ich weiß nicht wie ich damit umgehen soll 
bzw. kenn solche Segmentierungen nur aus dem Mikrocontroller.net 
Assembler Tutorial in dem aber nicht beschrieben ist wie ein compiler 
das erledigt. (..."man gcc" schau ich mir ein anderes mal an) :D
1
**** Build of configuration Release for project Pedelec ****
2
3
make all 
4
Building file: ../lcd.c
5
Invoking: AVR Compiler
6
avr-gcc -Wall -Os -fpack-struct -fshort-enums -ffunction-sections -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega8 -DF_CPU=8000000UL -MMD -MP -MF"lcd.d" -MT"lcd.d" -c -o "lcd.o" "../lcd.c"
7
../lcd.c: In function ‘init_lcd’:
8
../lcd.c:170:2: warning: implicit declaration of function ‘blinken’
9
Finished building: ../lcd.c
10
 
11
Building file: ../main.c
12
Invoking: AVR Compiler
13
avr-gcc -Wall -Os -fpack-struct -fshort-enums -ffunction-sections -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega8 -DF_CPU=8000000UL -MMD -MP -MF"main.d" -MT"main.d" -c -o "main.o" "../main.c"
14
Finished building: ../main.c
15
 
16
Building file: ../spi.c
17
Invoking: AVR Compiler
18
avr-gcc -Wall -Os -fpack-struct -fshort-enums -ffunction-sections -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega8 -DF_CPU=8000000UL -MMD -MP -MF"spi.d" -MT"spi.d" -c -o "spi.o" "../spi.c"
19
Finished building: ../spi.c
20
 
21
Building target: Pedelec.elf
22
Invoking: AVR C Linker
23
avr-gcc -Wl,-Map,Pedelec.map --gc-sections -mmcu=atmega8 -o "Pedelec.elf"  ./Pedelec/.metadata/.plugins/org.eclipse.cdt.make.core/specs.o  ./.metadata/.plugins/org.eclipse.cdt.make.core/specs.o  ./adc.o ./globalflag.o ./initialisierung.o ./interrupt.o ./lcd.o ./main.o ./mathfunction.o ./sinuskommutierung.o ./spi.o ./timer.o   
24
Finished building target: Pedelec.elf
25
 
26
Create Flash image (ihex format)
27
avr-objcopy -R .eeprom -O ihex Pedelec.elf  "Pedelec.hex"
28
Finished building: Pedelec.hex
29
 
30
Invoking: Print Size
31
avr-size --format=avr --mcu=atmega8 Pedelec.elf
32
AVR Memory Usage
33
----------------
34
Device: atmega8
35
36
Program:    6980 bytes (85.2% Full)
37
(.text + .data + .bootloader)
38
39
Data:       1272 bytes (124.2% Full)  <---- verdächtig?
40
(.data + .bss + .noinit)
41
42
43
Finished building: sizedummy
44
 
45
46
**** Build Finished ****

Übrigens werde ich wenn ich mit meinem Pedelec fertig bin hier alles als 
OpenSource freigeben. Falls ihr Tipps für mich habt bin ich dankbar.
zur Zeit Versuch ich erstmal die Kommunikation auf die Beine zu stellen 
(zwecks Debbugen mit "7 Segmentanzeige"). Die Struktur -als Konzept- der 
Motorsteuerung mit PWM, verketteter Liste, etc. steht so ungefähr.

von Rolf Magnus (Gast)


Lesenswert?

Johann L. schrieb:
> Daß Variabte 2 ist für globale und statischen Variablen eben nicht
> wirklich schneller.  Grund: Variante 1 initialisiert zum init-Zeit vor
> main, während Variante 2 erst dann läuft, wenn die Anwendung bereits
> gestartet ist.

Und welchen Unterschied macht es, ob das nun vor main() oder direkt am 
Anfang von main() gemacht wird? Warum sollte es mehr Zeit brauchen, wenn 
es in main() gemacht wird statt davor?

> Ob es bis zu main ein paar µs länger dauert ist idR vollkommen Banane.

Das ist allerdings richtig, aber es war ja deine Aussage, daß die 
Zuweisungen in main() erheblich länger dauern sollen.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Johanns Aussage

> Die zweite Variante ist wesentlich ineffizienter als die erste.

bezog sich natürlich auf die Speichereffizienz, nicht auf die
Rechenzeiteffizienz ;-)

von Peter D. (peda)


Lesenswert?

Yalcin schrieb:
> Data:       1272 bytes (124.2% Full)  <---- verdächtig?
> (.data + .bss + .noinit)

Das kracht definitiv.
Je nach Abschätzung des Stackverbrauchs sollten da max 80% stehen.


Peter

von Yalcin (Gast)


Lesenswert?

SOodann schließ ich mal mit einer Lösung das Problem ab.
Also, ich habe in Eclipse nicht benötigte Dateien mit "exclude from 
Project" aus dem Projekt ausgeschlossen. Ich war der meineung das nicht 
inkludierte *.c bzw. *.h Dateien vom Compiler automatisch ausgeschlossen 
werden.

Gruß Yalcin

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.