mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Structarray mit Adressproblemen in C


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
typedef struct
{
  UINT16 ids;
  UINT16 days;
  UINT16 switchOnTime;
  UINT16 switchOffTime;
}s_settings;

am Anfang meiner eeprom.c erzeuge ich mir ein Array davon, sodass ich in 
dieser c-Datei von überall darauf zugreifen kann:
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:
UINT8 I2C_EE_PageRead( uint16_t ReadAddr, uint16_t NumByteToRead, UINT8* pBuffer)
{
  UINT8 retVal;
.....
}

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

Autor: Keiner N. (nichtgast)
Datum:

Bewertung
1 lesenswert
nicht 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.

Autor: Rufus Τ. F. (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rufus Τ. F. (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Heiko (Gast)
Datum:

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

Autor: Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Carl D. (jcw2)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Heiko (Gast)
Datum:

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

Das habe ich jetzt auf
#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.

Autor: Ooops (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heiko schrieb:
> Ist der Stack stark begrenzt?

Den Stack bestimmst du im Linker Description File.

Autor: Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Nop (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.