Structarray mit Adressproblemen in C

Gast #5422571
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
Persönliche Seite
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.
Gast
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.
Persönliche Seite
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?
Gast
Rekursion kann ich eigentlich schon ausschließen. Aber vielleicht suche 
ich nochmal in dieser Richtung, ob ich doch irgendwo eine ungewollte 
Rekursion habe.
Gast
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?
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.
Gast
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.
Gast
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?
Gast
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...
Gast
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.
Gast
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 8 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.