Forum: Mikrocontroller und Digitale Elektronik Überschreiben von Strukturelementen


von Christian E. (eins)


Lesenswert?

Hallo zusammen,

ich habe einen LPC2294 mit dem RealView-Compiler. Dort habe ich eine 
globale Struktur angelegt:
1
#define MAX_ELEMENTS           16  
2
typedef struct
3
{
4
 int       n;
5
 char      szName[32];
6
} TEST;
7
8
static TEST g_sTest[MAX_ELEMENTS];

Die Elemnte dieser Struktur werden in einer Funktion gefüllt:
1
{
2
  g_sTest[nIndex].n = 0;
3
  strncpy(g_sTest[nIndex].szName, Name, sizeof(g_sTest[nIndex].szName));
4
  g_sTest[nIndex].szName[sizeof(g_sTest[nIndex].szName) - 1] = 0;
5
6
  printf("Ab hier werden die Werte der Struktur überschrieben");
7
}

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

von Andreas K. (a-k)


Lesenswert?

Stack overflow?

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Dietmar E (Gast)


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.

von Christian E. (eins)


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?

von Andreas K. (a-k)


Lesenswert?

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

von Dietmar E (Gast)


Lesenswert?

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

von Christian E. (eins)


Lesenswert?

Die vereinfachte Version geht leider auch nicht....

von Christian E. (eins)


Lesenswert?

Habe gerade mal eine lokale Variable angelegt:
1
char test [2];
2
3
test[0] = 't';
4
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.

von Stefan B. (stefan) Benutzerseite


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.

von Christian E. (eins)


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:
1
static TEST g_sTest[MAX_ELEMENTS] =
2
{
3
 {0, "01"},
4
 {0, "02"},
5
 {0, "03"},
6
 {0, "04"},
7
 {0, "05"},
8
 {0, "06"},
9
 {0, "07"},
10
 {0, "08"},
11
 {0, "09"},
12
 {0, "10"},
13
 {0, "11"},
14
 {0, "12"},
15
 {0, "13"},
16
 {0, "14"},
17
 {0, "15"},
18
 {0, "16"}
19
};

Vielen Dank für Eure Hilfe.

von Dietmar E (Gast)


Lesenswert?

Versuch es mal so, wäre kürzer:

static TEST g_sTest[MAX_ELEMENTS] = { 0 };

von Christian E (Gast)


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

von Christian E. (eins)


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:
1
#define MAX_ELEMENTS           16  
2
typedef struct Drive
3
{
4
 struct * Drive prev;
5
 struct * Drive next;
6
 char      szName[32];
7
} TEST;
8
9
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:
1
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

von Dietmar ohne E (Gast)


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)

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.