Forum: Mikrocontroller und Digitale Elektronik [ARM-GCC] Misaligned konstantes Array


von Mampf F. (mampf) Benutzerseite


Lesenswert?

Guten Morgen,

ich hab einen Cortex M1 (quasi M0 für FPGAs) und hab da ein seltsames 
Phänomen.

Beispiel in der main.c:
1
const uint8_t txdata[288] = { 0xff, 0xff, 0xff, 0xff, 0x4e, 0x3c, 0xf2, 0x7d, 0x38, 0x38, 0x5a, 0xd5, 0x66, 0xe3, 0x77, usw, };

wird zufällig ausgerichtet. Manchmal an 32Bit, was ich eigentlich 
angenommen hatte, aber oft auch nicht.

Ich hab den Parameter -mno-unaligned-access den Compiler-Schaltern 
hinzugefügt, aber es passiert immer noch.

Sicherlich kann man mit irgendeinem _attribute_ das forcieren, es wäre 
aber schön, wenn der Compiler das gleich richtig machen würde.


Kennt das Problem jemand?

Viele Grüße,
Mampf

von (prx) A. K. (prx)


Lesenswert?

Union aus Byte- und Wort-Array erzwingt Alignment.

von Dr. Sommer (Gast)


Lesenswert?

Mampf F. schrieb:
> wäre aber schön, wenn der Compiler das gleich richtig machen würde.

So wie er es macht ist es richtig, so wie vom Standard verlangt. Was du 
als richtig haben möchtest, ist unerheblich...

In C++ kannst du einfach alignas(4) davor schreiben. Für C hat der GCC 
ein Attribut: __attribute__((align(4))) .

Mampf F. schrieb:
> Ich hab den Parameter -mno-unaligned-access den Compiler-Schaltern
> hinzugefügt, aber es passiert immer noch.

Der bewirkt nur Unterschiede bei den Zugriffen, siehe Doku!

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Dr. Sommer schrieb:
> Mampf F. schrieb:
>> wäre aber schön, wenn der Compiler das gleich richtig machen würde.
>
> So wie er es macht ist es richtig, so wie vom Standard verlangt. Was du
> als richtig haben möchtest, ist unerheblich...

Der Standard kümmert sich wohl nicht um CPU-Architekturen ... Aber sowas 
provoziert doch Fehler ohne Ende - wobei das ist man bei C ja gewöhnt.

Ich nehme an, das kann mir mit lokalen Variablen auf dem Stack oder 
Übergabeparameter nicht passieren?

> In C++ kannst du einfach alignas(4) davor schreiben. Für C hat der GCC
> ein Attribut: __attribute__((align(4))) .

Hatte ich mir gewünscht, der Compiler würde das automatisch machen.

Solange es nur kontante Arrays betrifft, die im Flash/ROM landen ist der 
Aufwand überschaubar.

Bei Daten, die in bss landen wäre es auch blöd ... naja

>
> Mampf F. schrieb:
>> Ich hab den Parameter -mno-unaligned-access den Compiler-Schaltern
>> hinzugefügt, aber es passiert immer noch.
>
> Der bewirkt nur Unterschiede bei den Zugriffen, siehe Doku!

ok, danke^^

von Dr. Sommer (Gast)


Lesenswert?

Mampf F. schrieb:
> Aber sowas
> provoziert doch Fehler ohne Ende - wobei das ist man bei C ja gewöhnt.

Wo ist hier ein Fehler? Bei der korrekten Nutzung (also Zugriff ala 
txdata[3]) passiert nichts.

Mampf F. schrieb:
> Ich nehme an, das kann mir mit lokalen Variablen auf dem Stack oder
> Übergabeparameter nicht passieren?
Doch. Die sind nur so weit aligned wie nötig.

Mampf F. schrieb:
> Hatte ich mir gewünscht, der Compiler würde das automatisch machen.

Wozu sollte er unnötig Speicher verschwenden?

Mampf F. schrieb:
> Bei Daten, die in bss landen wäre es auch blöd ... naja
Die betrifft es genauso.

Die Frage ist natürlich: Warum soll das Array 4-Byte aligned sein? Ein 
byte-Array wird auch nur als byte dereferenziert, und bei Bytes ist das 
Alignment bei ARM egal.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Dr. Sommer schrieb:
> Mampf F. schrieb:
>> Aber sowas
>> provoziert doch Fehler ohne Ende - wobei das ist man bei C ja gewöhnt.
>
> Wo ist hier ein Fehler? Bei der korrekten Nutzung (also Zugriff ala
> txdata[3]) passiert nichts.

Ok, du hast recht - meine Verwendung von Pointern war falsch.

Der Compiler würde richtig darauf zugreifen, aber wenn ich per 
uint32-Pointer auf ein Byte-Array zugreife, muss ich dann eben aufpassen 
und es explizit alignen.

> Mampf F. schrieb:
>> Ich nehme an, das kann mir mit lokalen Variablen auf dem Stack oder
>> Übergabeparameter nicht passieren?
> Doch. Die sind nur so weit aligned wie nötig.
>
> Mampf F. schrieb:
>> Hatte ich mir gewünscht, der Compiler würde das automatisch machen.
>
> Wozu sollte er unnötig Speicher verschwenden?

Ja, das ist wahr ...

von Dr. Sommer (Gast)


Lesenswert?

Mampf F. schrieb:
> Der Compiler würde richtig darauf zugreifen, aber wenn ich per
> uint32-Pointer auf ein Byte-Array zugreife

Ja, das darf man so ohne weiteres natürlich nicht tun... Warum machst du 
das? Nimm doch ein uint32_t Array.

von Bernd K. (prof7bit)


Lesenswert?

Nimm ein Union aus Byte-Array und Long-Array. Das ist portabler als 
compilerspezifische Attribute und Pragmas und außerdem bildet es auch 
genau das ab was Du anscheinend später mit dem Array sowieso machen 
willst: Mal als byte und mal als long drauf zugreifen. Also nimm im 
Interesse der Lesbarkeit und Verständlichkeit auch die dafür 
vorgesehenen Typdeklarationen und Sprachkonstrukte.

Und bevor jetzt jemand kommt und Vorträge über Type-Punning mit Unions 
hält: Auch bevor seitens des Standardkomitees nachträglich nochmal 
schriftlich klargestellt wurde daß Type-punning mit Unions ab C99 
offiziell erlaubt ist war es schon unstrittig daß ein char-array sowieso 
immer alles aliasen durfte.

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.