Forum: PC-Programmierung Das Drama mit den Strings und Arrays in C.


von Christian J. (Gast)


Lesenswert?

Hallo,

ich dreh noch ab :-/

Eigentlich ganz einfach. Ich möchte einen Wochentag aus einer RTC 
drucken. Dazu definiere ich const char* const Tag[7], damit kein 
Initializer entsteht, der mir bei jedem Eintritt in die Routine ein 
Array einzeln füllt. Die Kürzel sollen im Flash Speicher liegen, ein 
Zeiger da drauf und dieser Zeiger soll dann in sprintf %s in den Zeit 
String gedruckt werden.

Das Ganze funktioniert NUR, wenn ich ein Element mit Zahl direkt 
anspreche Tag[2], vermutlich optimiert der GCC das dann. Sobald ich aber 
als Index eine Variable nehme, nämlich die aus der RTC: Time.wtag, also 
Tag[Time.day] dann steht da nur noch Müll auf dem Display oder der 
Rechner stürzt ab.

Bei abgeschalteter Optimierung im Debug Mode aber läuft das Ganze 
wieder. Was ist denn da nun kaputt ? :-(
1
///////////////////////////////////////////////////
2
// Druckt die Zeit und Datum ins Display
3
///////////////////////////////////////////////////
4
5
const char* const Tag[7] = {"So","Mo","Di","Mi","Do","Fr","Sa"};
6
7
void gfx_DrawDateTime()
8
{
9
    char buf[80];
10
11
    /* Format time */
12
    sprintf(buf, "%02u:%02u:%02u Uhr am %s,%02u.%02u.%04u", Time.hours,Time.minutes,Time.seconds,Tag[2],Time.date,Time.month,Time.year + 2000);
13
    TM_ILI9341_Puts(TransX(0),TransY(239), buf,&TM_Font_11x18,ILI9341_COLOR_WHITE, ILI9341_COLOR_BLACK);
14
}


Korrektur: Auch im Debug Mode nicht, er landet im HardFaultHandler, sah 
nur so als stünde das Richtige dort.

Gruss,
Christian

von Frickelfritze (Gast)


Lesenswert?

Christian J. schrieb:
> ich dreh noch ab :-/

Zitat:

Formatierung (mehr Informationen...)

1
C-Code
1
AVR-Assembler-Code
    .... etc

von Christian J. (Gast)


Lesenswert?

Frickelfritze schrieb:
> Formatierung (mehr Informationen...)

Wie meinen? Das ist ein Cortex 4 und Assemblercode habe ich nicht, nützt 
dir auch nichts.

von Frickelfritze (Gast)


Lesenswert?

Christian J. schrieb:
> Wie meinen?

Steht direkt im Block "Antwort schreiben", hier unten.
Wenn du das nicht verstehst ist dir nicht mehr zu helfen.

von Christian J. (Gast)


Lesenswert?

Lassen wir das und einen schönen Tag noch.

An alle anderen:

Schon ein

char wtag[3];
strcpy(wtag,Tag[Time.day]);

lässt den uC in den HardFaultHandler abstürzen als ich versuchte das 
Problem zu umschreiben.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Das sieht auf den ersten sehr oberflächlichen Blick völlig legal aus.
Ein reines C-Problem ("Drama") ist das nicht, das Problem wird in der 
Umgebung liegen.

Ist denn der Stack initialisiert und ausreichend Platz verfügbar?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Christian J. schrieb:
> Die Kürzel sollen im Flash Speicher liegen,

Sowas wie "Falsh" gibt es in C nicht.  Wenn überhaupt ist das nur in 
bestimmten C-Dialekten möglich; der von dir verwendete ist aber geheim.

von Christian J. (Gast)


Lesenswert?

Rufus Τ. F. schrieb:

> Das sieht auf den ersten sehr oberflächlichen Blick völlig legal aus.
> Ein reines C-Problem ("Drama") ist das nicht, das Problem wird in der
> Umgebung liegen.
>
> Ist denn der Stack initialisiert und ausreichend Platz verfügbar?

Ich habe den Stack mal von 256 Bytes auf 1k gesetzt, Platz genug ist ja 
da im STM32F4.

Ich bastel grad noch etwas aber wenn man const weglässt dann läuft es. 
Normalerweise sollte der Compiler ja const ins ROM legen, wobei const 
auch nur heisst, dass eine Zuweisung darauf nicht funktioniert. Ob ich 
explizit mit __attribute_(.rom) arbeiten muss weiss ich noch nicht.

Er mapped es derzeit in .rodata was nicht so verkehrt aussieht, wenn es 
global definiert wird

*(.rodata*)
 .rodata.str1.1
                0x080093bc       0x66 obj\release\src\graphik.o
 .rodata.Tag    0x08009422       0x15 obj\release\src\graphik.o
                0x08009422                Tag

nimmt man const weg liegt es in .data

*(.data*)
 .data.APBAHBPrescTable
                0x20000000       0x10 
obj\release\spl\src\stm32f4xx_rcc.o
 .data.SystemCoreClock
                0x20000010        0x4 
obj\release\spl\src\system_stm32f4xx.o
                0x20000010                SystemCoreClock
 .data.oldcolor.9705
                0x20000014        0x2 obj\release\src\graphik.o
 .data.Tag      0x20000016       0x15 obj\release\src\graphik.o
                0x20000016                Tag

lokal in der Routine muss es heissen:

static const char Tag[7][3] = {"So","Mo","Di","Mi","Do","Fr","Sa"};

damit es im Flash zu liegen kommt.

Ich denke ich lasse es so, ohne die Zeiger. War ja das Ziel sowas ins 
Flash zu legen, dass kein Initializer Code entsteht, der es aufbläht.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Hast du berücksichtigt, dass bei vielen RTCs die Wochentage nicht von 0
bis 6, sondern von 1 bis 7 gezählt werden? Du musst also von diesem Wert
evtl. 1 subtrahieren, bevor du ihn also Array-Index verwendest.

von Christian J. (Gast)


Lesenswert?

Yalu X. schrieb:
> sondern von 1 bis 7 gezählt werden?

ja, habe ich, im STM32 zählt sie von 1 bis 7. Das ist auch immer mein 
Problem, was ist Sonntag usw. Hier So = 1;

Läuft aber jetzt :-)
1
void gfx_DrawDateTime()
2
{
3
    static const char Tag[8][3] = {"So","Mo","Di","Mi","Do","Fr","Sa","--"};
4
    char buf[80];
5
    uint8_t index;
6
7
    // Evtl. Fehler abfangen
8
    index = (Time.day < 1 || Time.day > 7) ? 7 : (Time.day-1);
9
10
    /* Format time */
11
    sprintf(buf, "%02u:%02u:%02u Uhr am %s,%02u.%02u.%04u", Time.hours,Time.minutes,Time.seconds,Tag[index], Time.date,Time.month,Time.year + 2000);

von -.-.- (Gast)


Lesenswert?

Welches Drama? Ich sag dazu nur
https://de.wikipedia.org/wiki/The_C_Programming_Language

wie so oft gilt: Weil man selber in der Anwendung etwas falsch macht, 
ist nich die Programmiersprache schuld.

"Mit großer Macht kommt große Verantwortung". Wenn dir du mit der Macht 
die dir C gibt nicht umgehen kannst(Verantworung), dann musst du was 
anderes machen.

P.S.

Christian J. schrieb:
> Frickelfritze schrieb:
>> Formatierung (mehr Informationen...)
>
> Wie meinen? Das ist ein Cortex 4 und Assemblercode habe ich nicht, nützt
> dir auch nichts.

Viele Forumsmitglieder klicken den Thread gleich wieder weg, wenn sie 
unformatierten Code sehen...

von Walter S. (avatar)


Lesenswert?

Christian J. schrieb:
> Yalu X. schrieb:
>> sondern von 1 bis 7 gezählt werden?
>
> ja, habe ich, im STM32 zählt sie von 1 bis 7. Das ist auch immer mein
> Problem, was ist Sonntag usw. Hier So = 1;

in deinem ersten Post war das aber nicht berücksichtigt, war das jetzt 
der Fehler?
Wenn deine Time.day außerhalb des erlaubten Range liegt hat das ja 
wirklich nichts mit dem "Drama mit Strings und arrays in C" zu tun

von Christian J. (Gast)


Lesenswert?

Walter S. schrieb:
> in deinem ersten Post war das aber nicht berücksichtigt, war das jetzt
> der Fehler?

Nein. Die Verwendung von const char* const <ausdruck> erzeugt nach wie 
vor einen HardFault. Ich habe das Problem anders formuliert, was aber im 
Ergebnis aufs Gleiche hinauskommt. Warum das andere jetzt nicht 
funktioniert möchte ich jetzt nicht mehr herausfinden.

von Matthias K. (mkeller)


Lesenswert?

Interessant wäre das auf jeden Fall. Aber solange du genug Speicher 
hast, kannst du das const einfach weg lassen. Die paar bytes ... :)

Wie sieht es aus wenn du die Arraygröße explizit angibst? Also

Statt
1
const char* const Tag[7] = {"So","Mo","Di","Mi","Do","Fr","Sa"};
2
3
const char Tag[7][3] = {"So","Mo","Di","Mi","Do","Fr","Sa"};

Wenn ich beide Varianten bei meinem aktuellen Target (STM32F4 mit 
ChibiOS  3.0.3 und g++) einbinde kann ich ohne Probleme mit
1
  for(int i=0;i<7;i++)
2
  {
3
    chprintf((BaseSequentialStream*)&SD2,Tag[i]);
4
  }

die Tage ausgeben

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

Matthias K. schrieb:
> Wie sieht es aus wenn du die Arraygröße explizit angibst? Also

Das habe ich ja, s.o. Das * ist verschwunden, nur noch ein Array und 
const bzw. static sorgt dafür, dass er im ROM gemapped wird. Und das war 
ja das Ziel, weil sonst bei jedem Aufruf immer wieder aufs Neue der 
Array befüllt wird, was ja Quatsch ist.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Christian J. schrieb:
> Hier So = 1

Klaro, nur so ist Shabbat der 7. Tag :-)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Gib doch einfach mal den numerischen Wert von Time.day aus. Wenn der 
Wert > 6 ist, ist es normal, dass Dein Programm crasht. Dann ist Dein 
Array nämlich zu klein.

von DirkB (Gast)


Lesenswert?

Oder rechne noch Modulo 7

von ... wer nicht fragt bleibt d.... (Gast)


Lesenswert?

Wieviel Speicher belegt die Konstante bei dem fehlerhaften Verhalten? 
Das sollte im MAP-File stehen.

von Alex (Gast)


Lesenswert?

Moin,

Steppe doch im Debugger einfach mal durch den ASM-Code und schau welche 
Anweisung den Fault auslöst - dann weißt du wahrscheinlich schon woran 
es liegen könnte. Wenn nicht, dann lass dir im Faulthandler noch den 
Fehlergrund ausgeben...
HardFaults haben sich bei mir mit der Vorgehensweise eigentlich immer 
recht schnell geklärt.

Vielleicht ists ja auch etwas ganz anderes - C Libs nicht richtig 
eingebunden oder sonstwas...

mach doch z.b. mal nur char bla[5]; strcpy(bla,"test");
Wenn es da auch schon einen Fault gibt hat das Ganze auch nix mit dem 
RTC zu tun. Wenn doch, dann...

MfG Alex

von Matroska (Gast)


Lesenswert?

> Gib doch einfach mal den numerischen Wert von Time.day aus.
Wahrscheinlich falsch deklariert - man sieht ja nur das halbe Programm.
Du mußt mit struct und ggf. union arbeiten, wenn Du Time.day nutzen 
willst - sonst geht das nicht.

von Pandur S. (jetztnicht)


Lesenswert?

Debuggen gehoert zum Entwicklungskonzept. ... Moeglichkeiten :

-Simulator und durchsteppen
-Einsetzen und Ausgabe von Konstanten
-einfuellen und Lesen von Variablem per UART.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Oder D. schrieb:
> Debuggen gehoert zum Entwicklungskonzept.

Tse, Debugging und Simulation sind heutzutage wohl DIE Design-Pattern 
des Software-"Entwicklers".

Code reintippsen oder copy+paste, Debuggen oder Simulieren bis das 
rauskommt, was gewünscht ist, und dass weiter bis zum nächsten 
Code-Klumpen...

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Hallo Johann,

Johann L. schrieb:
> Tse, Debugging und Simulation sind heutzutage wohl DIE Design-Pattern
> des Software-"Entwicklers".

was soll den "Tse" sein?

mfg Torsten

von Pandur S. (jetztnicht)


Lesenswert?

>Tse, Debugging und Simulation sind heutzutage wohl DIE Design-Pattern
des Software-"Entwicklers".

>Code reintippsen oder copy+paste, Debuggen oder Simulieren bis das
rauskommt, was gewünscht ist, und dass weiter bis zum nächsten
Code-Klumpen...

Das war schon immer so. Nur ein paar akademische Freaks die nie ueber 
einen Hundertzeiler rauskamen, entwickeln ohne Debuggen, sind stolz auf 
keinen Fehler.

Meine Aussage ist sogar eher .. Man muss die zu verwendenden 
Debugschnittstellen bereits beim Design einplanen.

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.