Forum: Mikrocontroller und Digitale Elektronik Structarray mit Adressproblemen in C


von Heiko (Gast)


Lesenswert?

Hallo zusammen,

ich habe ein Problem mit einem Array von Structs in C, durch welches ich 
so langsam nicht mehr durchblicke.

In der Header Datei eeprom.h habe ich ein Struct definiert:
1
typedef struct
2
{
3
  UINT16 ids;
4
  UINT16 days;
5
  UINT16 switchOnTime;
6
  UINT16 switchOffTime;
7
}s_settings;

am Anfang meiner eeprom.c erzeuge ich mir ein Array davon, sodass ich in 
dieser c-Datei von überall darauf zugreifen kann:
1
s_settings settings[20];

Das Lesen und Beschreiben dieses Arrays scheint normal zu funktionieren.
Jetzt kommt das Komische: Ich habe eine Funktion in dieser Datei:
1
UINT8 I2C_EE_PageRead( uint16_t ReadAddr, uint16_t NumByteToRead, UINT8* pBuffer)
2
{
3
  UINT8 retVal;
4
.....
5
}

Wenn ich mir die größe in Bytes anschaue, ergibt sizeof(settings) = 160, 
was plausibel ist. Die Adresse von settings ist bei mir: 0x20003130. Ich 
würde jetzt erwarten, dass nun Speicher von 0x20003130 bis 0x200031D0 
reserviert wird. Allerdings ist die Adresse von der funktionslokalen 
Variable retVal = 0x20003177 was mitten drin im Speicherbereich von 
meinem Array liegt und natürlich zu Problemen führt. Wie kann das sein? 
Initialisiere ich mein Struct falsch?

Ich hoffe ich habe das Problem ausreichend beschrieben, damit mir jemand 
auf die Sprünge helfen kann, was ich falsch mache.

Viele Grüße, Heiko

von Keiner N. (nichtgast)


Lesenswert?

Moin,

wenn das tatsächlich der Fall sein sollte, zerschießt du dir an irgend 
einer anderen Stelle den Stack.

Such mal nach überschrittenen Array Grenzen. String Funktionen sind ein 
beliebter Kandidat.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Heiko schrieb:
> Allerdings ist die Adresse von der funktionslokalen Variable retVal =
> 0x20003177 was mitten drin im Speicherbereich von meinem Array liegt ....

Funktionslokale Variablen ("automatische Variablen") werden auf dem 
Stack angelegt. Wenn der Stack sich mit Variablen außerhalb von 
Funktionen überschneidet, ist irgendwas grundlegendes kaputt.

Entweder hast Du aufgrund von nicht gezeigtem Code einen massiv 
überlaufenden Stack (z.b. durch viel zu große automatische Variablen 
oder durch Rekursion), oder aber Dein Startup-Code bzw. Linker-Skript 
ist kaputt und legt Stack und Daten wirr an.


> Initialisiere ich mein Struct falsch?

Wo initialisierst Du es? Du legst ein Array an (auf die korrekte Weise), 
gibst aber keine Initialwerte an, damit wird jedes Element des Arrays 
(und also auch jedes Element jeder einzelnen Struktur) mit 0 
initialisiert.

Das ist soweit alles korrekt.

von Heiko (Gast)


Lesenswert?

Mein Projekt ist recht groß, allerdings achte ich schon immer darauf, 
nicht allzu große Variablen anzulegen, die dann auf dem Stack landen.

Kann ich mir meinen aktuellen Stackpointer anzeigen lassen? Ich verwende 
CooCox.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Heiko schrieb:
> Kann ich mir meinen aktuellen Stackpointer anzeigen lassen?

Im Debugger sowieso, aber recht nah dran bist Du auch mit der Adresse 
Deiner automatischen Variablen. Das genügt zum Einschätzen bereits.

> Mein Projekt ist recht groß, allerdings achte ich schon immer darauf,
> nicht allzu große Variablen anzulegen, die dann auf dem Stack landen.

Dir ist genau klar, welche Art von Variablen auf dem Stack und welche 
nicht auf dem Stack landen?

Und Du kannst Probleme mit Rekursion ausschließen?

Verwendest Du dynamische Speicherverwaltung? Verwendest Du die Funktion 
alloca?

von Heiko (Gast)


Lesenswert?

Rekursion kann ich eigentlich schon ausschließen. Aber vielleicht suche 
ich nochmal in dieser Richtung, ob ich doch irgendwo eine ungewollte 
Rekursion habe.

von Heiko (Gast)


Lesenswert?

Mir scheint mein Stack tatsächlich etwas zu groß zu werden. Man sieht 
mit jeder Funktion, die ich tiefer eintauche, dass er immer näher an 
meine Variablen im Heap drankommt. Ich sollte mich wohl mal um 
Stackgröße kümmern. Habe ich mich bisher nicht so mit auseinandergesetzt 
(ich habe einen STM32F103VET6). Der hat ja recht viel RAM. Ist der Stack 
stark begrenzt?

von Carl D. (jcw2)


Lesenswert?

Heiko schrieb:
> Mir scheint mein Stack tatsächlich etwas zu groß zu werden. Man sieht
> mit jeder Funktion, die ich tiefer eintauche, dass er immer näher an
> meine Variablen im Heap drankommt. Ich sollte mich wohl mal um
> Stackgröße kümmern. Habe ich mich bisher nicht so mit auseinandergesetzt
> (ich habe einen STM32F103VET6). Der hat ja recht viel RAM. Ist der Stack
> stark begrenzt?

Das schöne ist, daß der überlaufende Stack genau den Verlauf der 
Übeltäter protokolliert. Wenn also immer wieder die gleiche Code-Adresse 
bzw. Folge von Code-Adressen zu finden ist und die jeweils auch noch auf 
ein BL oder ähnlich zeigt, dann hast du sie am Wickel.

von Heiko (Gast)


Lesenswert?

Ich glaube ich hab's gefunden. In meiner "startup_stm32f10x_hd.c" war
1
#define STACK_SIZE       0x00000100      /*!< The Stack size suggest using even number     */

Das habe ich jetzt auf
1
#define STACK_SIZE       0x00001000      /*!< The Stack size suggest using even number     */

vergrößert. D.h. ich habe meinen Stack von winzigen 256Bytes auf 
4096Bytes vergrößert. Ist das ein Problem, wenn ich an dieser Variable 
im Startup rumfummele? Mein Chip hat ja 60kB SRAM, also bleibt mir noch 
genug Rest.

Vielen Dank für die vielen Antworten und Tipps.

von Ooops (Gast)


Lesenswert?

Heiko schrieb:
> Ist der Stack stark begrenzt?

Den Stack bestimmst du im Linker Description File.

von Heiko (Gast)


Lesenswert?

Mit dem Linker Description File kenne ich mich so gar nicht aus.

Ich habe ja im startup_stm32f10x_hd.c modifiziert und das Ergebnis sah 
richtig aus. Hätte ich an anderer Stelle was ändern sollen?

von Heiko (Gast)


Lesenswert?

Ups, hab gerade gemerkt, dass ich mich eben verrechnet habe. Ich habe 
die Stacksize nicht von 256Bytes auf 4kB vergrößert, sondern von 1kB auf 
16kB, da ja der Stackpointer auf 32Bit Werte verweist, oder?
Dann reduziere ich die Stacksize wieder etwas...

von Nop (Gast)


Lesenswert?

Ooops schrieb:

> Den Stack bestimmst du im Linker Description File.

Nein, bei Coocox bestimmt man den im Quelltext über die Größe dieses 
Arrays. Das wird dann im Linkerfile richtig weiterverwurstet.


Heiko schrieb:
> da ja der Stackpointer auf 32Bit Werte verweist, oder?

Schau Dir einfach den Datentyp des Stack-Arrays an, das sollte uint32_t 
sein. Also 32bit-Werte.

von Heiko (Gast)


Lesenswert?

Stimmt. Ist 32Bit.
Den Stack habe ich jetzt auf 4kB angepasst, das sollte wohl auf ewig 
reichen für dieses Projekt.

Also vielen Dank nochmal an alle und einen schönen Abend.

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.