Guten Morgen,
ich habe hier ein Problem und ich komme einfach nicht auf die Lösung.
Wahrscheinlich ist es etwas ganz einfaches, aber ich sehe es einfach
nicht. Ich möchte einen String, den ich aus einem EEPROM hole, in ein
globale char Array schreiben. Ich versuche das auf folgende Weise:
1
externchardevName[16];
2
3
voidsetName(void)
4
{
5
charname[16];
6
7
getDeviceName(name);//Name aus EEPROM holen
8
dbg_printf("%s\r",name);
9
//memcpy(devName, name, 16);
10
11
//sprintf(devName, "%s", (const char*)name);
12
//strncpy(devName, name,3);
13
//strcpy((char *)devName, (const char *)name);
14
dbg_printf("%s\r",devName);
15
}
Das Problem ist jetzt, dass sich der Controller immer wenn ich versuche
auf das globale Array zu schreiben, aufhängt. Er verweigert komplett
seinen Dienst, nur ein Reset hilft dass noch. Architektur ist ein ARM
Cortex M0.
Ich habe wie ihr seht schon auf mehrere Arten versucht, den String in
"devName" zu bekommen. Bei allen Varianten das gleiche Verhalten. In
"name" steht der richtige String und wird auch richtig ausgegeben
(dbg_printf(...) ).
Habt ihr eine Idee, was das Problem sein könnte?
Gruß,
Bean
Ist es sicher, dass der String NULL-terminiert ist? Sonst schreibst du
dir sonstwas kaputt.
Warum kopierst du nicht einfach die 16Byte vom einen ins andere oder
liest dein EEPROM-String direkt in die globale Variable?
Edit:
und das "extern"... die Variable gibts aber irgendwo?
Mr Bean schrieb:> extern char devName[16];
mittels 'extern' deklarierst du nur.
Du sagst also im Klartext: Irgendwo existeriert ein entsprechendes Array
mit diesem Namen.
Aber du definierst es so nicht.
Definition: dadurch wird auch tatsächlich entsprechender Speicher
angelegt
Deklaration: es wird mitgeteilt wie etwas aussieht. Aber dieses etwas
muss an anderer Stelle definiert sein.
Hast du eine entsprechende Definition an anderer Stelle im Programm?
Hallo,
vielen Dank für eure Antworten. Also die externe Variable ist
deklariert. An einer anderen Stelle (bewusst so gemacht).
Den Gedanken mit der Nullterminierung hatte ich auch schon. Darum habe
ich es auch schon mit strncpy versucht. Hier wird die Länge ja
vorgegeben.
Hat trotzdem nicht funktioniert.
Außerdem wird der korrekte String mit printf ja auch ausgegeben. Wenn er
keine Terminierung hätte, würde das dort ja schon auffallen oder?
Gruß,
Bean
Mr Bean schrieb:> Außerdem wird der korrekte String mit printf ja auch ausgegeben. Wenn er> keine Terminierung hätte, würde das dort ja schon auffallen oder?
normalerweise ja. Das fällt da meistens schon auf. Was wird denn bei der
ersten Ausgabe angezeigt?
Du kannst ja mal probieren, ganz einfach
a) dir die Länge des Strings ausgeben lassen. Alles kleiner als 16 ist
ok.
b) einen mit Sicherheit "sauberen" String zuzuweisen
Mr Bean schrieb:> Also habe versucht einen sauberen String zuzuordnen. Funktioniert leider> auch nicht.>> Adresse der Variable devName laut Debugger: 0x20002F90>> Gruß,> Bean
Und ist das eine gültige Adresse für Variablen (laut Datenblatt) ?
Mr Bean schrieb:> Also habe versucht einen sauberen String zuzuordnen.
darf man fragen welchen?
Nicht das wir aneinander vorbeireden.
Nur um das klarzustellen: in einem Array der Länge 16, kannst du einen
String mit 15 darstellbaren Zeichen gerade noch speichern. 16
darstellbare Zeichen wären zu viel.
Ich fürchte du solltest mal den kompletten Code zeigen.
Compiliert alles ohne Warnungen?
Ist die Variable devName[] vielleicht viel kleiner als angenommen?
Also es compiliert ohne Fehler und ohne Warnungen.
Ist ein sehr großes Projekt. Wie gesagt, funktioniert der Code aber. Nur
das Hinzufügen von der Stringzuweisung bringt die Anwendung zum Absturz.
Sobald ich diese Operationen wieder entferne, habe ich keine Probleme
mehr.
Den String habe ich folgendermaßen zugeordnet:
Mr Bean schrieb:> Also es compiliert ohne Fehler und ohne Warnungen.
Das heisst nichts.
"Das Flugzeug frühstückt im Tannenbaum." ist auch ein deutscher Satz,
gegen den kein Duden etwas einzuwenden hätte. Compiler überprüfen nur,
ob du dich an die Sprachregeln hältst. Ob du logische Fehler hast bzw.
ob du Speicher überrennst, ist damit noch lange nicht geprüft.
Mr Bean schrieb:> Also es compiliert ohne Fehler und ohne Warnungen.> Ist ein sehr großes Projekt. Wie gesagt, funktioniert der Code aber. Nur> das Hinzufügen von der Stringzuweisung bringt die Anwendung zum Absturz.> Sobald ich diese Operationen wieder entferne, habe ich keine Probleme> mehr.> Den String habe ich folgendermaßen zugeordnet:>
1
strcpy(devName,"Hallo");
> Der passt also in das Array rein.>> Gruß,> Bean
Ich habe die Variablendefinition von devName[] noch nicht gesehen.
Sondern nur die Deklaration. Ist es sicher, dass devName[] 16 Elemente
hat?
Mr Bean schrieb:> Ist ein sehr großes Projekt.
Es ist auch nicht gesagt, dass das Problem nicht ganz woanders sitzt und
du hier nur die Auswirkungen siehst.
Symptom ist nicht dasselbe wie Ursache.
Hallo, ich habe einfach die Frage beantwortet, ob das Projekt ohne
Warnungen und Fehler compiliert wird. ;-) Dass das nicht bedeutet, dass
keine Fehler vorhanden sind, die das Programm zum absturz bringen
können, ist mir klar.
Die Variabe devName wird in main.c folgendermaßen global angelegt:
Ja Heinz, das glaube ich mittlerweile auch. Es ist auch nicht das erste
Mal, dass ich solche stringoperationen mache. Bisher immer ohne
Probleme. Aber wie finde ich die Ursache dann?
Gruß,
Bean
Mr Bean schrieb:> Hallo, ich habe einfach die Frage beantwortet, ob das Projekt ohne> Warnungen und Fehler compiliert wird. ;-) Dass das nicht bedeutet, dass> keine Fehler vorhanden sind, die das Programm zum absturz bringen> können, ist mir klar.>> Die Variabe devName wird in main.c folgendermaßen global angelegt:>
1
chardevName[0x10];
Was passiert, wenn du gleich in main als allererstes den strcpy machst?
Wenn das klappt (und davon ist auszugehen), dann schiebst du den in der
Programmlogik immer weiter nach hinten, bis es das erste mal kracht.
Mr Bean schrieb:> char devName[0x10];
wer hat dir denn das beigebracht --> Zahlen in irgendwelchen "krusen"
Zahlensystemen, bei der Deklaration von Variablen. Zum Glück hast du
kein Feld mit 1000 Elementen vereinbart. Bei 0x03E8 müsste ich erst mal
meinen Taschenrechner rauskramen....
progger schrieb:> Mr Bean schrieb:>> char devName[0x10];>> wer hat dir denn das beigebracht --> Zahlen in irgendwelchen "krusen"> Zahlensystemen, bei der Deklaration von Variablen. Zum Glück hast du> kein Feld mit 1000 Elementen vereinbart. Bei 0x03E8 müsste ich erst mal> meinen Taschenrechner rauskramen....
Das ist jetzt zwar OffTopic, aber:
Das Zahlensystem an sich ist doch wurscht. Für mich fällt das unter die
Kategory "Magic Numbers".
Woher soll den der Schreiber von Modul_3.c wissen, welche Größe die
Variable von main.c hat? Oder ob der Schreiber von main.c die Größe
geändert hat.
Das kann man nur über ein #define (o.ä.) lösen
Also, auch wenn ich die Variable devName in main.v verwende, schmiert
das Programm ab. Ich habe die Variable nun mal initialisiert mit
"={"HALLO"}".
Wenn ich versuche, die Variable in main.c (am Anfang) auf dem Terminal
auszugeben, schmiert das Programm schon ab??
Mr Bean schrieb:> Also, auch wenn ich die Variable devName in main.v verwende, schmiert> das Programm ab. Ich habe die Variable nun mal initialisiert mit> "={"HALLO"}".> Wenn ich versuche, die Variable in main.c (am Anfang) auf dem Terminal> auszugeben, schmiert das Programm schon ab??
Was genau funktioniert jetzt nicht?
Die Initialisierung mit einem String, oder das Ausgeben des Strings?
Das Ausgeben des Strings funktioniert nicht.
Sobald ich versuche, den String auszugeben, sieht es so aus, als ob der
Controller nicht einmal los läuft.
Habe die Zeile
1
dbg_printf("%s\r",devName);
direkt am Anfang von main.c eingebaut. --> Controller läuft nicht los.
Zeile wieder entfernt --> Programm läuft.
Mr Bean schrieb:> Das Ausgeben des Strings funktioniert nicht.> Sobald ich versuche, den String auszugeben, sieht es so aus, als ob der> Controller nicht einmal los läuft.> Habe die Zeile>
1
dbg_printf("%s\r",devName);
> direkt am Anfang von main.c eingebaut. --> Controller läuft nicht los.> Zeile wieder entfernt --> Programm läuft.
1
intmain()
2
{
3
strcpy(devName,"Juhu");
4
dbg_printf("%s\n",devName);
5
6
allesweiterewirdauskommentiert
7
}
musst du irgend etwas initialisieren, damit die Debug Ausgabe zum
Terminal funktioniert? Wenn ja, dann kommt dieser Teil noch davor.
Ok, also wenn ich das mache, dann kommt "HALLO" auf dem Terminal raus.
Jetzt heißt es also, alles der Reihe nach wieder inzukommentieren oder
wie?
Gruß,
Bean
Mr Bean schrieb:> Ok, also wenn ich das mache, dann kommt "HALLO" auf dem Terminal raus.> Jetzt heißt es also, alles der Reihe nach wieder inzukommentieren oder> wie?
Kann man machen. Man kann aber auch systematischer vorgehen.
Eventuell wird zur Laufzeit ein Speicherbereich überschrieben. Sowas
könnte man zum Beispiel mit statischer Codeanalyse herausfinden, wobei
man dafür ein entsprechendes Tool braucht.
Was auch oft schon helfen kann: Einfach mal auf einer anderen Plattform
mit besseren Debugging-Möglichkeiten übersetzen, z.B. auf dem PC mit
z.B. gcc (MinGW oder Cygwin) oder Clang/LLVM. Bestimmte Funktionsaufrufe
und Initialisierungen muss man dann natürlich in #ifdefs packen. Aber
man erkennt, ob die eigentliche Programmlogik tut oder nicht. Auch hat
man auf dem PC auf jeden Fall einen Debugger zur Verfügung (z.B. gdb).
Auf der Zielhardware steht einem sowas nicht unbedingt zur Verfügung.
Genau das ist eines meiner Probleme. Ich arbeite mit KEIL. Auf dem
Controller läuft noch ein eigenständer BLE Stack. Dieser verhindert ein
ordentliches Debuggen, da dieser eine Laufzeitkontrolle macht. Mann kann
also nicht eben mal anhalten und wieder laufen lassen. Das einzigste was
geht, ist anhalten und sich die Register/Speicher zu diesem Zeitpunkt
anschauen. Weiterlaufen lassen ist leider nicht möglich.
Gruß,
Bean
Das schränkt natürlich enorm ein. Gibt es keine "Debug-Version" des
BLE-Stacks? Wie soll man denn da sinnvoll entwickeln können?
Wenn der Controller sich aufhängt: Kannst du den Debugger anhalten und
schauen, wo das Programm steht? Lässt sich da was rauslesen?
Es sieht ganz nach einem Speicherkonflikt aus.
Was macht denn dbg_printf() genau (Sourcecode)?
Ja, das stimmt, das schränkt wirklich ein. Aber gut, bisher sind wir
klar gekommen. Habe den Übeltäter auch gefunden. Es war eine Funktion
des BLE Stacks. Diese hat den String verwendet / falsch verwendet. Diese
Funktion möchte den String als "const char" ansonsten schlägt ein
exception handler zu... Fieses Ding. Hat mich ganz schön Nerven
gekostet.
Vielen Dank an alle die geholfen haben!
Gruß,
Bean