Nach Initialisierung falsche Werte im Struct

OP #7705390
Lesenswert?

Halo Kollegen. Komme mit Initialisierung einer Struktur nicht weiter. Mikrokontroller - STM32-F103-Olimex, IDE – Eclipse, Compiler - GCC, G++

Der Compiler meckert nicht aber die Werte der initialisierten Struktur sind falsch.

Die Struktur beschreibt einen Zeichensatz (Font) für die Ausgabe am LCD Display.

1
//Display.h
2

3
#parma   //--- wird vom Compiler ignoriert ???
4

5
typedef struct {
6
const short *table;  // Tabelle mit den Font Daten
7
  short width;    // Breite des Zeichens (in Pixel)
8
  short height;    // Hoehe  des Zeichens (in Pixel)
9
}Font_t;

Anderen Daten und Code sind im „Display.c“ gesammelt um den Fehler zu lokalisieren.

Die Font Tabelle (*table).

1
const short Arial_7x10_Table [] = {
2
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Ascii = [ ]
3
0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00, // Ascii = [!]
4
 . .  insgesamt 95 Zeilen, je 10 Hex Werte
5
};

Initialisierung

1
Font_t Arial_7x10 = {      //Variable Arial_7x10 erzeugen, Typ Font_t
2
  .table = Arial_7x10_Table,  // Adresse der ZeichenTabelle zuweisen
3
  .width = 7,        // Schriftbreite setzen
4
  .height = 10        // Schrifthöhe   . . .
5
};

Beim Debuggen - kein Wert stimmt: Variable .width sollte = 7 sein, .height = 10. ---Bild „StructDaten.png“

Tabelle hat eine falsche Adresse.
---Bild „Tabelle.png“.

Man könnte es mit der Tabellenadresse vergeigen, aber 2 anderen Werte sind doch DIREKT zugewiesen.

Was mache ich falsch?????

Angehängte Dateien:
Persönliche Seite #7705420
Lesenswert?

Entweder dein Startupcode oder Linkerscript ist defekt, oder die Variable Arial_7x10 wird von einem "wilden Pointer" überschrieben (Buffer Overflow o.ä.).

Wenn das Programm ganz am Anfang ist (Anfang der main()), sind die Daten dann richtig? -> Watchpoint drauf setzen und laufen lassen.

Sind die Daten da schon falsch? Breakpoint im Startupcode NACH das " bcc CopyDataInit" setzen und schauen ob es dann stimmt - wenn ja, Watchpoint setzen und laufen lassen. Wenn nein, ist was am Startupcode/Linkerscript kaputt.

Beitrag #7705425 wurde von einem Moderator gelöscht.
OP #7705944
Lesenswert?

Niklas G. schrieb:

Wenn das Programm ganz am Anfang ist (Anfang der main()), sind die Daten dann richtig? -> Watchpoint drauf setzen und laufen lassen.

von Oliver S. (oliverso) Stackoverflow, Array out of bounds, oder wie auch immer du die Daten überschreibst.

Danke für den Tipp. Hab einen kleine Struct erzeugt und diesen intialisiert an der gleichen Stelle mit dem alten Struct - auch der neuer Strukt wurde falsch initialisiert.

Am Anfang des Programms (Anfang der main()) hat alles sauber geklappt. Muss mal sehen wie ich den Stack checken kann.

#7706013
Lesenswert?

Artur schrieb:

Am Anfang des Programms (Anfang der main()) hat alles sauber geklappt.

Die Structs werden nicht durch "Magie" befüllt, das macht der µC schon schön selber in seinem Startup-Code. Wenn du deinen Breakpoint zu früh hast, kannst du dem µC zuschauen, wie er der Reihe nach seine globalen Variablen und Structs initialisiert. Am Anfang von "main" ist er damit fertig...

OP #7709711
Lesenswert?

Hallo Kollegen. Hatte in der Woche leider nicht viel Zeit aber immer hin gibt es ein Ergebniss. . .

So lief es weiter

  • die Tabelle(nur 2 Zeilen), die Definition der Struktur und die Initialisierung --> ganz am Anfang der main() eingetragen -> hat nicht geholfen

  • die Tabelle fest definiert -> statt [] ein [2][10] eingetragen

1
const unsigned short Arial_7x10_Table[2][10] = {
2
  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 
3
  {0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00},
4
};

Erst jetzt wurde der Struct ordentlich initialisiert - alle Werte in den Variable richtig eingetragen.

  • Definition der Struktur aus main() in "Display.h" versetzt - funktionierte auch.

  • komplette Tabelle am Anfang der Main() eingetragen (95 Zeilen). Compiler hat sich "verschluckt" und ist mit der Meldung "undefined reference to memcpy'" ausgestiegen. Der Eintrag #include "string.h" hat nicht geholfen. Erst eine weitere Ergänzung der Tabellendefinition mit "static" hat mich weitergebracht

1
"static const unsigned short Arial_7x10_Table[95][10] . . . "
  • Die gesamte Tabelle ins "Display.h" verschoben - geht auch :-)

Also mit einer Schrift (Font) könnte man es so belassen. Wenn man aber 2 - 3 Fonts hat, wird die Header "überladen" wirken. Geschickter wäre es pro Font eine Separate Datei zu haben - aber genau das funktioniert noch nicht hinbekommen.

Bin dran :-)))

Persönliche Seite #7709717
Lesenswert?

Oliver S. schrieb:

Spätestens an der Stelle sollte klar sein, daß deine toolchain kaputt ist.

Es ist extrem unwahrscheinlich, dass der GCC bei so etwas simplen versagt.

Artur schrieb:

So lief es weiter

Du doktorst an den Symptomen rum. Du hast irgendwo einen Buffer Overflow o.ä. Den findest du so nicht. Der wird dich später anderweitig in den allerwertesten beißen, du hast so eine Zeitbombe im Code.

Auf die Gefahr mich zu wiederholen: Benutze einen Data Watchpoint. Damit hast du das eigentliche Problem in 2 Minuten gefunden. Ohne Rätselraten und Rumprobieren.

Persönliche Seite #7709723
Lesenswert?

Oliver S. schrieb:

Es ist extremst unwahrscheinlich, das eine intakte toolchain ein „undefined reference to memcpy“ auswirft.

Das ist sogar sehr wahrscheinlich. Intakte toolchains tun das ständig. Bei fehlerhaftem Code eben. Der hier sehr wahrscheinlich vorliegt. Aber diesen kennen wir ja nicht.

Artur schrieb:

komplette Tabelle am Anfang der Main() eingetragen (95 Zeilen).

Wenn man die Tabelle als lokale Variable in die main() schreibt MUSS eine intakte Toolchain diesen Fehler liefern, wenn man versucht von anderen Stellen aus "direkt" darauf zuzugreifen.

OP #7709730
Lesenswert?

Oliver S. schrieb:

Spätestens an der Stelle sollte klar sein, daß deine toolchain kaputt ist.

Könnte gut sein. Leider hab ich von Einstellungen in "Eclipse" nicht viel Ahnung. Die IDE wurde mir vor Jahren vom Arbeiskollegen in Frankfurt eingerichtet. Ich bin "weit weg" aus Frankfurt nach Paderborn umgezogen und den Kontakt verloren. So programmiere ich immer noch Hobbymäßig mit der alten Einrichtung / Umgebung. Leider, sind Programmierer "meiner Klasse"(Über 70 und immer noch in "C") in meiner Umgebung nicht zu finden. Würde mich tierisch freuen eine "verwandte Sehle" in der Nähe zu haben.

Könnte aber auch gut sein dass die IDE sehr "mager" eingerichtet ist so dass die Programme auf mehreren MK laufen werden.

Persönliche Seite #7709759
Lesenswert?

Artur schrieb:

Die IDE wurde mir vor Jahren vom Arbeiskollegen in Frankfurt eingerichtet.

PS: Mittlerweile kommt die STM32CubeIDE mit einem simplen Installer. Da bekommt man mit wenigen Klicks ein aktuelles (!) funktionsfähiges Gesamtpaket und muss auch nix konfigurieren. Man hat sehr schnell ein Projekt für den gewünschten Controller angelegt, kann sich grafisch die Takt- und Pin-Konfiguration zusammenklicken und bekommt den entsprechenden Code generiert. Das kann sich jeder selbst einrichten.

#7709776
Lesenswert?

Niklas G. schrieb:

Man hat sehr schnell ein Projekt für den gewünschten Controller angelegt, kann sich grafisch die Takt- und Pin-Konfiguration zusammenklicken

Naja, das ist für einen "Anfänger" schon eine kleine Herausforderung da es beim "Zusammenklicken" schon einige Sachen zu beachten gibt die sich als kleine Fallstricke herausstellen können. Aber man muss ja nicht die graphische Initialisierung wählen sondern kann sich nach herkömmlicher Art sein Projekt in der CubeIDE zusammen- stellen - einfach alle Sourcen in ein neues leeres Projekt herein- kopieren. Das würde sich auch anbieten wenn der TO mal sein komplettes Projekt posten würde.

Die CubeIDE zu verwenden ist auf jeden Fall empfehlenswert um von der halbgaren Eclipse-Installation wegzukommen. Ja ich weiss, Eclipse ist dann immer noch präsent ...

OP #7709784
Lesenswert?

Wastl schrieb:

Niklas G. schrieb:

Da wird es scheinbar mit "mangelnder Beratungsresistenz" immer schwieriger.

Artur schrieb:

Programmierer "meiner Klasse"(Über 70

Da habt Ihr scheinbar gar nicht so unrecht :-)

Pas Projekt ist inzwischen "etwas" gröser geworden(siehe Bild). Ein Paar Verzeichnisse fehlen noch. Ich versuche den "Sieben Segment Display" mit einen "graphischen Display" zu ersetzen.

Würde es helfen die main(), Display.c und die Display.h zur Verfühgung zu stellen? Soll ich den Code direkt hier einfügen? Oder ich kann auch das Projekt komplett mal zippen.

Angehängte Dateien:
#7709881
Lesenswert?

Artur schrieb:

komplette Tabelle am Anfang der Main() eingetragen (95 Zeilen). Compiler hat sich "verschluckt"

Das ist mir im Nachhinen klar: die grosse Struct in Main anzulegen sprengt die Grösse des Stacks die per default irgendwo festgelegt wird.

"Grosse" Datenmengen sollte man immer Modul-global oder total global anlegen, dann belasten sie nicht den Stack.

Hab ich überlesen dass das schon jemand erwähnt hat? Dann sorry für die Verdoppelung .....

Moderator Persönliche Seite #7710930
Lesenswert?

Artur schrieb:

weitere Ergänzung der Tabellendefinition mit "static" hat mich weitergebracht

"static const unsigned short Arial_7x10_Table[95][10] . . . "

Die gesamte Tabelle ins "Display.h" verschoben - geht auch :-)

Du hast offenbar keine Ahnung, was Du da tust.

Durch "static" beschränkst Du den Scope für die Tabelle auf die aktuelle Übersetzungseinheit. Wenn Du dann zusätzlich noch die Tabelle ins Display.h verschiebst, ist das ein Doppel-Eigentor.

Folge ist nämlich, dass die Tabelle damit für jede Übersetzungseinheit, in welcher Du Display.h inkludierst, noch einmal neu erzeugt wird. Wenn also ein Dutzend von C-Sources

1
#include "Display.h"

aufrufen, hast Du auch ein dutzendmal die Tabelle im Speicher - ob Flash oder auch RAM... siehe oben.

Mit Deinen Aktionen dokterst Du nur an den Symptomen, ohne den eigentlichen Fehler auszumerzen. Du hast höchstwahrscheinlich einen Buffer-Overflow für die Variable, die im Source vor Deiner Array-Definition liegt. (*1)

Beispiel:

1
#include <stdio.h>
2
#include <string.h>
3

4
char buffer[4];
5
int variable;
6

7
int main ()
8
{
9
    strcpy (buffer, "hello"); // Dieser Befehl überschreibt variable
10

11
    printf ("%d\n", variable);
12
}

(*1) Muss nicht zwingend so sein, je nach Compiler oder Optimierung kann die Reihenfolge der Variablen im RAM abweichen. Wenn man beide Variablen in eine Struct packt, dann passierts aber ziemlich sicher.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren