String in global char Array schreiben!?

Gast #4333841
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
extern char devName[16];
2

3
void setName(void)
4
{
5
  char name[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?
Gast
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
1
   ...
2
   strcpy( devName, "juhu" );
Gast
Also habe versucht einen sauberen String zuzuordnen. Funktioniert leider 
auch nicht.

Adresse der Variable devName laut Debugger: 0x20002F90

Gruß,
Bean
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.
1
  strcpy( devName, "123456789012345" );
wäre also noch in Ordnung
1
  strcpy( devName, "1234567890123456" );
hingegen ist nicht mehr ok.
Gast
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
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?
Gast
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
char devName[0x10];

Gruß,
Bean
Gast
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
char devName[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.
Gast
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
1
#define devName_Length 0x10
2

3
char devName[devName_Length];
Gast
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??
Gast
Hallo, also die Größe ist über ein #define definiert. ;-)
Wollte euch nur nicht mit solchen Kleinigkeiten "nerven" ;-)
1
#define ARRAY_SIZE 0x10

Gruß,
Bean
Mr Bean schrieb:
> Hallo, also die Größe ist über ein #define definiert. ;-)
> Wollte euch nur nicht mit solchen Kleinigkeiten "nerven" ;-)
>
1
#define ARRAY_SIZE 0x10
>
> Gruß,
> Bean

Um Offtopic zu bleiben: hübscher Name (ARRAY_SIZE). Es weiß dann jeder 
was gemeint ist und wo es zu verwenden ist. ;-)
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?
Gast
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
int main()
2
{
3
  strcpy( devName, "Juhu" );
4
  dbg_printf( "%s\n", devName );
5

6
alles weitere wird auskommentiert
7
}

musst du irgend etwas initialisieren, damit die Debug Ausgabe zum 
Terminal funktioniert? Wenn ja, dann kommt dieser Teil noch davor.
Gast
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.
Gast
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)?
Gast
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

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 11 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.