Forum: Compiler & IDEs gcc variable placement


von fourth (Gast)


Lesenswert?

Fuer einen Forthinterpreter wollte ich um ein besseres Verstaendnis
zu gewinnen, einige Arrays auf glatte Adressen legen.

Herausgekommen ist das:
1
//unsigned int Memory[MEMORY_SIZE];
2
//unsigned int Stack[STACK_SIZE];
3
//unsigned int RStack[STACK_SIZE];
4
//char TIB[TIB_SIZE];
5
//char *Current_TIB_pos;
6
7
struct MyMEMstr
8
{
9
  unsigned int  Memory[MEMORY_SIZE]  __attribute__ ((aligned (64))) __attribute__ ((packed));
10
  unsigned int  Stack[STACK_SIZE]  __attribute__ ((aligned (32))) __attribute__ ((packed));
11
  unsigned int  RStack[STACK_SIZE]  __attribute__ ((aligned (32))) __attribute__ ((packed));
12
  char      TIB[TIB_SIZE];
13
} MyMEM[1];
14
15
unsigned int *Memory  = MyMEM[0].Memory;
16
unsigned int *Stack  = MyMEM[0].Stack;
17
unsigned int *RStack  = MyMEM[0].RStack;
18
char *TIB    = MyMEM[0].TIB;
19
char *Current_TIB_pos;

Legt die Arrays auf:
Memory:0x8200[2048] Stack:0x9200[32] RStack:0x9240[32] TIB:0x9280[80]

Geht das eigentlich auch einfacher?

von Bernd K. (prof7bit)


Lesenswert?

fourth schrieb:
> einige Arrays auf glatte Adressen legen.
> Geht das eigentlich auch einfacher?

Du kannst das packed weglassen, es erfüllt hier keinen Zweck. Und das 
struct ebenso und ich sehe auch keinen Grund warum Du ein array mit 
einem Element anlegst.

Wenn Die arrays auf "glatten" Adressen liegen sollen dann reicht das 
aligned attribut vollkommen aus.

: Bearbeitet durch User
von fourth (Gast)


Lesenswert?

> Wenn Die arrays auf "glatten" Adressen liegen sollen dann reicht das
> aligned attribut vollkommen aus.
Ja, fuer glatte Adressen reichts wohl, aber die Reihenfolge
war mir nicht genehm.
Daher die Konstruktion mit dem struct.

Das packed ist tatsaechlich ueberfluessig.

> Und das struct ebenso
Dann landet Memory[], gefolgt von RStack, Stack und TIB im RAM.
So wollte ich das aber nicht...

> ein array mit einem Element anlegst.
Damit der struct mit seinen Komponenten auch alloziert wird.

von Nop (Gast)


Lesenswert?

fourth schrieb:

>> ein array mit einem Element anlegst.
> Damit der struct mit seinen Komponenten auch alloziert wird.

Wird er auchm wenn Du das ohne Array anlegst. Aus "} MyMEM[1];" wird 
dann "} MyMEM;". Beim Zugriff muß das [0] natürlich dann weg.

von fourth (Gast)


Lesenswert?

> Wird er auchm wenn Du das ohne Array anlegst.

Hmm, tatsaechlich.
Ich bin verbluefft.

ST-Joke:
 Riker lookes puzzled 

von Nop (Gast)


Lesenswert?

Bernd K. schrieb:

> Du kannst das packed weglassen, es erfüllt hier keinen Zweck. Und das
> struct ebenso

Das bewirkt zumindest, daß die Anordnung im Speicher so ist wie 
deklariert. Würde man die Arrays einfach so deklarieren, dann liegen sie 
zwar üblicherweise auch aufeinanderfolgend im RAM, aber garantiert ist 
das nicht.

Will man also aus irgendwelchen Gründen Kontrolle über das 
Speicherlayout von mehreren Variablen, dann bietet sich ein struct 
durchaus an.

Das struct hat aber noch einen Vorteil: man kann den kompletten 
Speicherzustand der simulierten Maschine elegant mit einem Pointer an 
Funktionen herumreichen. Außerdem erleichtert die Typdefinition, in der 
die Arraygrößen ja enthalten sind, auch statische Codeanalyse, ob man 
out of bounds zugreift.

von fourth (Gast)


Lesenswert?

> Das bewirkt zumindest, daß die Anordnung im Speicher so ist wie
> deklariert. Würde man die Arrays einfach so deklarieren, dann liegen sie
> zwar üblicherweise auch aufeinanderfolgend im RAM, aber garantiert ist
> das nicht.

Ja, so war mir ja auch. Ohne struct tut der Compiler nach
eigenem Ermessen das im RAM anordnen.

Mit align alleine, verschwendet er sogar Speicherplatz, naemlich:

Memomry[2048]
RStack[32]
TIB[80]
Stack[32]

Da bleibt eine Luecke hinter dem TIB.


> ob man out of bounds zugreift.

Da schlaegt bei dem verwendeten de-luxe-Controller dann gnadenlos
die MMU zu.

von Nop (Gast)


Lesenswert?

fourth schrieb:

>> ob man out of bounds zugreift.
>
> Da schlaegt bei dem verwendeten de-luxe-Controller dann gnadenlos
> die MMU zu.

Nicht unbedingt, denn wenn Du z.B. über das Memory-Array hinausschreibst 
und in das Stack-Array hinein (welches dahinter beginnt), dann wird die 
MMU dazu gar nichts sagen, weil der Prozeß ja tatsächlich in beide 
Arrays reinschreiben darf. Das Programm wird dann aber nicht mehr wie 
gewünscht funktionieren.

von fourth (Gast)


Lesenswert?

> dann wird die MMU dazu gar nichts sagen, weil der Prozeß ja
> tatsächlich in beide Arrays reinschreiben darf.

Ich koennte zwischen Heap und Stack mit der MMU eine "Luecke"
konfigurieren. Das wuerde die MMU dann zum Sprechen bringen.

von fourth (Gast)


Lesenswert?

P.S.:
Bei der Forthmaschine wacht der Interpreter schon darueber
das sich da nix dicker macht.

von Bernd K. (prof7bit)


Lesenswert?

fourth schrieb:
>> Wird er auchm wenn Du das ohne Array anlegst.
>
> Hmm, tatsaechlich.
> Ich bin verbluefft.

Warum? Was hättest Du sonst erwartet? Daß er den Inhalt der Variablen im 
Kopf behält statt sie im Speicher abzulegen?

von Nop (Gast)


Lesenswert?

fourth schrieb:

> Ich koennte zwischen Heap und Stack mit der MMU eine "Luecke"
> konfigurieren.

Das wäre möglich, wenn das Struct an geeignete Adressen gelegt wird, 
wozu Du den Linker allerdings erst anweisen müßtest. Das Padding 
dazwischen könntest Du dann manuell so machen, daß eine Page frei 
bleibt. Parallel dazu könntest Du dann eine weitere Datenstruktur in 
genau diese Page linken, die Du dann für einen anderen Task nutzen 
kannst.

von fourth (Gast)


Angehängte Dateien:

Lesenswert?

> Warum? Was hättest Du sonst erwartet? Daß er den Inhalt der Variablen im
> Kopf behält statt sie im Speicher abzulegen?

Naja, normalerweise benutze ich Pointer auf Structs.
Da ist es schon sinnig mit einem [1] die Adresse auch zu erzeugen.

> Das wäre möglich, wenn das Struct an geeignete Adressen gelegt wird,
> wozu Du den Linker allerdings erst anweisen müßtest. Das Padding
> dazwischen könntest Du dann manuell so machen, daß eine Page frei
> bleibt. Parallel dazu könntest Du dann eine weitere Datenstruktur in
> genau diese Page linken, die Du dann für einen anderen Task nutzen
> kannst.

Die kleinste Einheit mit der die betreffende MMU das koennte,
waeren 512 byte. Wenn das ein kritisches Steuerungssystem
werden sollte, wuerde ich das wohl sogar machen um einen
Ueberlauf des (User-)Stacks zu detektieren. Fuer Interrupts
hat der Controller ohnehin noch einen eigenen Stack.

An dem "vergifteten" Bereich haette die "andere" Task aber
wenig Freude. Dem wuerde die MMU ihr auch dazwischenfahren.


An dem Controller haengt u.a. noch ein HY57V281620 SDRAM.
Nach Datenblatt sollte der 134,217,728 bit (16 MByte) haben.

Nach meinen Tests ist der aber doppelt so gross und bringt
32 MByte an seine Beine. Ich habe mal den Memtest des
Boardherstellers entsprechend aufgebohrt und der laueft
fehlerfrei durch.

Wie kommt denn sowas...


P.S.: map4k mappt 4k (16 bit-)Worte und nicht etwa Bytes.

von Bernd K. (prof7bit)


Lesenswert?

fourth schrieb:
> Naja, normalerweise benutze ich Pointer auf Structs.
> Da ist es schon sinnig mit einem [1] die Adresse auch zu erzeugen.

Was hast Du gegen den adress-operator? Der ist genau dafür da. Ein 
einelementiges Array dazu zu missbrauchen erzeugt lediglich ein WTF??? 
beim Leser.

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.