www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Überschreiben von Strukturelementen


Autor: Christian E. (eins)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich habe einen LPC2294 mit dem RealView-Compiler. Dort habe ich eine 
globale Struktur angelegt:
#define MAX_ELEMENTS           16  
typedef struct
{
 int       n;
 char      szName[32];
} TEST;

static TEST g_sTest[MAX_ELEMENTS];

Die Elemnte dieser Struktur werden in einer Funktion gefüllt:
{
  g_sTest[nIndex].n = 0;
  strncpy(g_sTest[nIndex].szName, Name, sizeof(g_sTest[nIndex].szName));
  g_sTest[nIndex].szName[sizeof(g_sTest[nIndex].szName) - 1] = 0;

  printf("Ab hier werden die Werte der Struktur überschrieben");
}

Bis zum printf läuft auch alles so, wie ich es erwarte. Sobald ich aber 
die Zeile mit dem printf (ein einfaches return oder andere Funktionen) 
aufrufe, ändern sich die Werte meiner Struktur.

Was mache ich falsch bzw. wie würdet ihr diesen Fehler suchen?

Dankeschön,

Christian

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stack overflow?

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

Bewertung
0 lesenswert
nicht lesenswert
Hmm. nIndex bleibt kleiner als MAX_ELEMENTS?

Dann kommt womöglich der Stack dem Speicherbereich ins Gehege, in dem Du 
das statische Array abgelegt hast.

Autor: Dietmar E (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schwer lesbarer Code. Schreib es doch so:

{
    TEST *slot = g_STest + nIndex;

    strncpy(slot->szName, Name, sizeof(slot->szName) - 1);
}

Das extra-Schreiben der 0 ist überflüssig, wenn man sie nie überschreibt 
(da globale Arrays sowieso mit 0 initialisiert sind).

Woher dein Problem kommen könnte: wie die anderen schon sagen, vieleicht 
ist nIndex zu gross? Oder der Rest der Funktion (wenn es einen gibt) hat 
einen Fehler, der den Stack überschreibt.

Autor: Christian E. (eins)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich vermute auch ein Problem mit dem Stack (nIndex ist sogar nur 0 oder 
1). Wenn ich MAX_ELEMENTS auf 4 setze, klappts. Wie kann ich den 
feststellen, dass ich ein Problem mit dem Stack habe?

Hab mir gerade das Memory Window mal angesehen. Dort wird die Struktur 
an der Adresse 0x400016AC abgelegt. Nach dem Füllen ist dort alles 
richtig. Nach dem printf steht dort ein völlig anderer Wert. Allerdings 
steht in der folgenden Adresse (0x400016B0) der Wert 0x400016AC (<- 
meine Strukturanfangsadresse). Kann das ein Problem beim Retten und 
Wiederherstellen der Werte sein?

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau dir doch mal den Wert vom Stack-Pointer an. Oder ersatzweise die 
Adresse einer lokalen Variablen.

Autor: Dietmar E (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast Du es mal mit der vereinfachten Schreibweise versucht? Auch 
Compiler haben manchmal Fehler.

Autor: Christian E. (eins)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die vereinfachte Version geht leider auch nicht....

Autor: Christian E. (eins)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe gerade mal eine lokale Variable angelegt:
char test [2];

test[0] = 't';
test[1] = 't';

die Werte dieser Variablen (Adresse 0x400016C0) werden beim strncpy 
überschrieben. Das heisst doch, dass sich hier meine Speicherbereiche 
überlappen, denn die Adresse 0x400016C0 sollte doch eigentlich noch zu 
meiner Struktur gehören.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es ist müßig, hier über Codefragmente zu spekulieren.

Das Überschreiben kann z.B. vollkommen legal sein, wenn sich der Fokus 
der Variable test ändert - typisch für lokale Variablen in einem eigenen 
Block...

Du solltest den Quellcode eines Minimalprogramms und das 
Linkercontrolscript (bzw. ggf. die ROM/RAM/Stack-Einstellungen in einer 
IDE) posten.

Autor: Christian E. (eins)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Problem gelöst:

leider hat der RealView-Compiler ein Problem, wenn die Elemente der 
Struktur nicht initialisiert sind. Er legt zwar ohne Initialiserung den 
Speicher der Struktur an, legt dort aber trotzdem noch andere Sachen ab 
und überschreibt die Strukturvariablen. Meine Initialiserung sieht dann 
folgendermaßen aus:
static TEST g_sTest[MAX_ELEMENTS] =
{
 {0, "01"},
 {0, "02"},
 {0, "03"},
 {0, "04"},
 {0, "05"},
 {0, "06"},
 {0, "07"},
 {0, "08"},
 {0, "09"},
 {0, "10"},
 {0, "11"},
 {0, "12"},
 {0, "13"},
 {0, "14"},
 {0, "15"},
 {0, "16"}
};

Vielen Dank für Eure Hilfe.

Autor: Dietmar E (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuch es mal so, wäre kürzer:

static TEST g_sTest[MAX_ELEMENTS] = { 0 };

Autor: Christian E (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Dietmar,

das war mein erster Versuch. Das ging leider nicht. Nur, wenn jedes 
Element einzeln inititialisert wird, geht's.

Danke für die Hilfe,

Christian

Autor: Christian E. (eins)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da bin ich wieder,

wie schon erwähnt, funktionieren einige Strukturen mittlerweile. Leider 
habe ich noch Probleme mit Strukturen in Strukturen. Die können nämlich 
mit Hilfe der "Einzelinitialisierung" vor dem Überschreiben geschützt 
werden. Ein Beispiel wäre:
#define MAX_ELEMENTS           16  
typedef struct Drive
{
 struct * Drive prev;
 struct * Drive next;
 char      szName[32];
} TEST;

static TEST g_sTest[MAX_ELEMENTS];

Hat jemand eine Idee, wie ich diese Strukur "einzeln" initialisieren 
kann?

Wenn ich mir den Assembler Code für das Überschreiben der Strukturwerte 
ansehe:
0x00002014  E3500000  CMP       R0,#g_ucMinVolume(0x00000000)

wird dort eine Variable (g_ucMinVolume) benutzt, die dort überhaupt 
nichts zu suchen hat. Wie kann ich denn herausfinden, wo dewr Schuh 
drückt?

Vielen Dank für die Hilfe,

Christian

Autor: Dietmar ohne E (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Hat jemand eine Idee, wie ich diese Strukur "einzeln" initialisieren
>kann?

Einer Struktur einen Wert zuzuweisen, z.B. komplett löschen, geht ja so 
direkt nur über memset() aus der stdlib.h etwa so:

memset (&Structvariable, 0, sizeof(STRUCTTYP));


RealView!

Ja, das hat mich auch schon geärgert, daß man nur zwischen Cholera und 
Pest wählen kann, nämlich entweder alles initialisieren oder nichts, 
halbe-halbe will das Ding unter keinsten Umständen.

Und das wäre beides wichtig, daß es geht!!!

Letztendlich werde ich den Compiler über einen nicht angegebenen 
RAM-Bereich über das Linker-Script austricksen müssen, ein Scratch-Pad 
außerhalb der Memory-Map anlegen, vielleicht funktioniert schon ein mit 
EMPTY definierter Block mitten im RAM, um Variablen über einen Reset 
hinaus zu retten, obwohl ich diese Methode überhaupt nicht so cool 
finde.

Oder gibt es doch noch die Möglichkeit, nur Strukturen nach Reset nicht 
zu initialisieren? Muß ich doch gleich mal ausprobieren!


Gruß

Dietmar (ohne E)

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.