Forum: Mikrocontroller und Digitale Elektronik malloc, strncpy auf STM32F4 keine Funktion


von Marcel F. (kellertuer)


Angehängte Dateien:

Lesenswert?

Hallo, bei mir zeigt strncpy keine Wirkung! Zuerst dachte ich, es liegt 
an der newlib. Bin aber mittlerweile am steppen im dissasembly und dort 
ist hinter strncpy eine Funktionalität hinterlegt. Es werden auch die 
Adressen der Strings geladen und auch das zu schreibende Zeichen kann 
ich erkennen. Jedoch passiert an der Stelle (strb.w r5, [r4], #1), an 
der das Zeichen in den neuen String kopiert werden sollte nichts. Das 
disassembly ist angefügt. Der Code lautet
1
  const char* from = "12345678";
2
  char *to = "yyyyyy";
3
  strncpy(to, from+2, 5);

Was läuft falsch?

von Marcel F. (kellertuer)


Lesenswert?

OK, Lösung gefunden:

Wenn ich schreibe
1
char to[6];
 dann wird die Variable irgendwo im RAM angelegt und kann verändert 
werden. Wenn ich aber schreibe
1
char to = "yyyyyy";
 dann wird die Variable irgendwo im Flash angelegt und kann nicht 
verändert werden.

Warum ist das so und wie kann ich festlegen, welche Variable ich wohin 
haben möchte?

von Karl H. (kbuchegg)


Lesenswert?

Marcel F. schrieb:

> disassembly ist angefügt. Der Code lautet
1
  const char* from = 
2
> "12345678";
3
>   char *to = "yyyyyy";
4
>   strncpy(to, from+2, 5);
>
> Was läuft falsch?

Dein C Verständnis.
Genauer gesagt deine Kenntnisse über String-Verarbeitung in C.

von Karl H. (kbuchegg)


Lesenswert?

Marcel F. schrieb:
> OK, Lösung gefunden:
>
> Wenn ich schreibe
>
1
> char to[6];
2
>
> dann wird die Variable irgendwo
> im RAM angelegt und kann verändert werden.

Logisch. Genau das hast du ja auch mit dem Array ausgedrückt.
1
   to
2
   +---+---+---+---+---+---+
3
   |   |   |   |   |   |   |
4
   +---+---+---+---+---+---+
schreibst du auch noch eine Initialisierung dazu, dann wird der Speicher 
auch gleich noch auf definierte Werte gesetzt.
1
char to[6] = "abcd";
1
   to
2
   +---+---+---+---+---+---+
3
   | a | b | c | d | \0|   |
4
   +---+---+---+---+---+---+

> Wenn ich aber schreibe
>
1
> char* to = "yyyyyy";
2
>
> dann wird die Variable irgendwo im Flash angelegt
> und kann nicht verändert werden.

Auch logisch.
Die Pointer Variable liegt im SRAM. UNd dieser Pointer wird so 
eingerichtet dass er auf ein String-Literal (eine konstanter String) 
zeigt. Denn "yyyyy" ist eine Stringkonstante und für dich unveränderbar.
1
   to
2
   +-----+
3
   | o------------------->"yyyyy"
4
   +-----+
und da String-Literale per Definition unveränderbar sind, darf sie der 
Compiler auch in Speicher legen, der vom Programm aus nicht veränderbar 
ist.
Du könntest den Pointer auf was anderes zeigen lassen, wenn du willst
1
  char* to = "yyyyyy";
1
   to
2
   +-----+
3
   | o-------------------->"yyyyy"
4
   +-----+     
5
                
6
                    "Hallo Du, Copyright by me"
1
  to = "Hallo Du, Copyright by me";
1
   to
2
   +-----+
3
   | o---------+           "yyyyy"
4
   +-----+     |
5
               |
6
               +--->"Hallo Du, Copyright by me"
aber das ändert nichts daran, dass auch dieses Stringliteral "Hallo Du, 
Copyright by me" ein Stringliteral und als solches unveränderbar ist.


Der Compiler darf sogar soweit gehen und mehrere derartige Verweise zu 
einem einzigen zusammenführen. Denn wie gesagt: Die String-Konstante ist 
für dich ja tabu, kann sich also daher während eines Programmlaufs nicht 
verändern.
1
  char* to = "yyyy";
2
  char* to2 = "yyyy";
1
   to
2
   +-----+
3
   | o------------------->"yyyyy"
4
   +-----+                 ^
5
                           |
6
                           |
7
   to2                     | 
8
   +-----+                 |
9
   | o---------------------+
10
   +-----+

von Marcel F. (kellertuer)


Lesenswert?

OK, danke für die ausführliche Erklärung. Hab lange nichts mit Strings 
in C gemacht, daher war mir das nicht bewusst. Ich dachte, dass
1
char var[3]="abc"
 und
1
char* var = "abc"
 das gleiche ist :)

Ach und ja, es sollte außerdem
1
char var[4]="abc"
 heißen, damit die Null noch reinpasst ;)

von Karl H. (kbuchegg)


Lesenswert?

Marcel F. schrieb:

> Ach und ja, es sollte außerdem
>
1
> char var[4]="abc"
2
>
> heißen, damit
> die Null noch reinpasst ;)

es sollte eigentlich
1
char var[] = "abc";
heißen. Denn dann zählt der Compiler für dich den String ab und 
dimensioniert das Array gerade groß genu, dass der String mit allem drum 
und drann gerade noch reinpasst.

Wenn du allerdings dann da mit einem strncat noch was hinten drann 
hängen willst, dann bist DU dafür verantwortlich, dass das Array dafür 
auch groß genug ist.

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.