Forum: Compiler & IDEs Speicheradresse von globalen Variabeln ändern


von Albi G. (deralbi)


Lesenswert?

Hallo...
Ich hab nen Problem mit meinem AVR32. Ich hab eine recht große 
Speicherauslastung (großer Stack).
Nun ist es mitlerweile so, dass sich mein Heap (gloabele Variablen) und 
mein Stack gegenseitig überlappen. Das ist ja kein Zustand, der 
erwünschenswert ist.

Komisch sind bei mir die Adressen der globalen Variabeln. Die liegen 
ungewöhnlich hoch. Ich frage mich warum..?


int Global = 40;

int main(void)
{
  volatile int a = 0;
  volatile int b = 1234;

  a = ((int)&Global);

  a = 0; //Debugbreakpoint

return 0;
}

Global liegt bei Adresse 2244. warum? Der Heap fängt doch schon viiiel 
weiter unten an. (Eigentlich sogar bei  0)
Nun frage ich mich, wie man das ändern kann.

In meinem reellen Fall (nicht nur das Test-Mini-Programm) habe ich 
einige globale Variablen.. die kleinse Adresse, die ich bei ihnen 
gefunden habe liegt bei 6500. Ich muss die in den Speicherbereich 
zwischen  0 und 2000 drücken. Wie geht das?

Kann da jemand helfen?

(b liegt übrigens bei 32760.. also 32kb-8Byte.. passt also! nur der heap 
ist mist)

von Peter D. (peda)


Lesenswert?

Albi G. wrote:
> Nun ist es mitlerweile so, dass sich mein Heap (gloabele Variablen) und
> mein Stack gegenseitig überlappen. Das ist ja kein Zustand, der
> erwünschenswert ist.

Nö, das ist sogar verboten.
Globale Variablen müssen immer gültig sein, d.h. Stack macht Schrott 
daraus, wenn er reinläuft.


> Komisch sind bei mir die Adressen der globalen Variabeln. Die liegen
> ungewöhnlich hoch. Ich frage mich warum..?

Wenn die Variablen global sind, ist es doch wurscht, was zuerst kommt.
Ich habs beim WINAVR auch mal erlebt, daß er erst die globalen Variablen 
und dann den Stack von oben her angelegt hat.

Es sei denn, Du benutzt globale Variablen für lokale Verwendung.
Dann bist Du selbst Schuld, wenn der Compiler sie nicht besser aufteilen 
kann.
Globale Variablen können (dürfen) nicht überlagert werden!


Peter

von Albi G. (deralbi)


Lesenswert?

Jajajaja.. das ist mir doch klar, deswegen frage ich, wie ich das 
verhindern kann. ;-)

Wenn ich auf dem Stack 29kb brauche und der AVR 32kb ram hat, dann 
bleiben mir nur noch 3kb frei. Der Stack macht nix verbotenes.. das ist 
so gewollt.

Scheiße is halt, dass die globalen Variablen so missplatziert sind.
Würden sie bei 0 beginnen würde alles passen. Ich hab das vorher ja 
durchgerechnet.
Ich frag mich was vor der Adresse 6500 gespeichert wird... ob die NewLib 
des AVR32 so viel braucht? :-(/

Vllt weiß jemand noch mehr.

von Falk B. (falk)


Lesenswert?

@ Albi G. (deralbi)

>Scheiße is halt, dass die globalen Variablen so missplatziert sind.

Kann ich mir schwer vorstellen. Dann müsste ja quasi das Linkerscript 
eine fehlerhafte RAM-Aufteilung vornehmen. Schau doch mal das Mapfile 
an, dort sollte das alles drinstehen.

>Ich frag mich was vor der Adresse 6500 gespeichert wird... ob die NewLib
>des AVR32 so viel braucht? :-(/

Maybe?

MFG
Falk

von Simon K. (simon) Benutzerseite


Angehängte Dateien:

Lesenswert?

So, ich habe mit DerAlbi jetzt mal rumgesessen. Folgendes ist dabei 
herausgekommen:

Testprogramm:
1
#include <stdio.h>
2
3
int g_Var = 1234;
4
5
int main()
6
{
7
  
8
  while(1);
9
  
10
  
11
  return 0;
12
}
Compileraufruf
1
make -k all 
2
Building file: ../main.cpp
3
Invoking: AVR32/GNU C++ Compiler
4
avr32-g++ -O0 -g3 -Wall -c -fmessage-length=0 -mpart=uc3a0512 -MMD -MP -MF"main.d" -MT"main.d" -o"main.o" "../main.cpp"
5
Finished building: ../main.cpp
6
 
7
Building target: cpptest.elf
8
Invoking: AVR32/GNU C++ Linker
9
avr32-g++ -Wl,-Map,Mapfile.map -mpart=uc3a0512 -o"cpptest.elf"  ./main.o   
10
Finished building target: cpptest.elf

So. Aufteilung der Speicherbereiche (Extrakt aus dem Mapfile)
1
Name             Origin             Length             Attributes
2
FLASH            0x80000000         0x00080000         axrl !w
3
INTRAM           0x00000000         0x00010000         axw !rl
4
USERPAGE         0x80800000         0x00000200
5
FACTORYPAGE      0x80800200         0x00000200
6
*default*        0x00000000         0xffffffff

Interner RAM ab 0x00000000 und Flash ab 0x80000000. Soweit Ok.

Den Rest des Mapfiles hänge ich an.

Man sieht im Mapfile, dass die komplette Standardbibliothek gelinkt 
wird. Mit allen Modulen und somit allen globalen Variablen und 
sämtlichem Code.

Die Frage nun: Warum ist das so? Das Testprogramm beinhaltet doch keinen 
einzigen Funktionsaufruf.

PS: g_Var wird bei
1
 .data          0x000008d0        0x4 ./main.o
2
                0x000008d0                g_Var
angelegt.

von Falk B. (falk)


Lesenswert?

@ Simon K. (simon)

>Man sieht im Mapfile, dass die komplette Standardbibliothek gelinkt
>wird. Mit allen Modulen und somit allen globalen Variablen und
>sämtlichem Code.

Das ist link ;-)

>Die Frage nun: Warum ist das so? Das Testprogramm beinhaltet doch keinen
>einzigen Funktionsaufruf.

Vielleicht gibts da irgendwelche Optionen ala cleanup/optimize, die 
bewirkt, dass nur die WIRKLICH verwendeten Funktionen im Code landen.

MFG
Falk

von Simon K. (simon) Benutzerseite


Lesenswert?

Das ist natürlich das naheliegendste. Allerdings haben wir diesbezüglich 
schon rumgesucht. Sowohl bei google, als auch bei den OnlineDocs zu den 
Komanndozeilen-Parameter...

Normalerweisem, so wurde gesagt, müsste das der Linker automatisch 
hinkriegen. Aber irgendwas verhindert das jetzt..

von Albi G. (deralbi)


Lesenswert?

Mich stören ja auch nichtmal wirklich die Funktionen... man bekommt 
unnütze Funktionen sehr wohl aus dem Binary..  aber es sind bei weiten 
noch viiiel zu viele Funktionen drin.
Hauptproblem ist einfach, das die ganze Bibliothek meinen wertvollen 
Speicher zumüllt, ohne dass dieser wirklich effektiv genutzt wird.

Auch wenn man die Standardbibliothek rausnimmt und die daraus genommenen 
Funktionen (sind ja nur 4 Stück) selbst implementerit, fallen nur 4kb 
ram-speicher weg.
Die Adressen liegen immernoch bei >2000. Lasse ich noch mehr 
bibeliotheken weg, so wird auch auf den Startup-Code verzichtet und dann 
geht gar nix mehr.

Sowas blödes. Es frustriert.

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.