Forum: Mikrocontroller und Digitale Elektronik sprintf() und char*


von Stefen (Gast)


Lesenswert?

Hallo,

in meinem Programm funktionert das kopieren des strings irgendwie nicht, 
obwohl der Rückgabe Wert der sprintf() richtig ist, an was könnte das 
liegen???
1
char* ar;
2
int tmp = 0;
3
tmp = sprintf(ar,"test"); // tmp ist dann 4

Gruß

von Thomas B. (detritus)


Lesenswert?

dein ar ist ein zeiger, der nicht initialisiert ist. Daher überschreibst 
dein sprintf Speicherbereiche, die nicht dafür reserviert sind.
Besser so (Speicher für den String reservieren und die Adresse des 
Speicherbereichs dem sprintf geben):
1
char ar [5];
2
int tmp = 0;
3
tmp = sprintf(&ar[0],"test"); // tmp ist dann 4
4
oder 
5
tmp = sprintf(ar,"test"); // tmp ist dann 4

von Patrick K (Gast)


Lesenswert?

Beispielsyntax:
1
char mystring[20];
2
3
long mylong;
4
5
 
6
7
mylong=1234;
8
9
sprintf(mystring,"<%lu>",mylong);
10
11
// mystring now has:
12
13
//      < 1 2 3 4 > \0

von Stefen (Gast)


Lesenswert?

Vielen Dank für euere Antwort.
aber das mit dem festen Array möchte ich nicht, weil die Anzahl der 
Zeichen im String ist variable, ich glaube mit malloc wird auch 
funktionieren???

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> ich glaube mit malloc wird auch funktionieren???

Schon, aber Du musst malloc vor dem Aufruf von sprintf aufrufen, um 
einen ausreichend langen Puffer anzufordern.
Sicherheitshalber solltest Du übrigens snprintf verwenden, dem wird 
als zweites Argument die Länge des Puffers übergeben, was "buffer 
overflows" vermeiden hilft.

von Stefen (Gast)


Lesenswert?

ist es eigentlich üblich in der uC-Welt (im Vergleich zum PC) mit malloc 
und delete zu arbeiten, was dann automatisch heisst mit dem Heap??

nächste Frage:
ine meinem Programm möchte ich viel text über die UART verschicken, so 
eine Art diagnose beim Starten oder bei fehler...., was macht ihr denn 
so in dem Fall? ich glaube nicht dass man in einer Funktion wartet bis 
das ganze Array gesendet ist, kann ja vielleicht ein paar ms dauern??

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

malloc und delete passen sowieso nicht zusammen.

new und delete  (C++)

malloc und free (C)

Nein, üblicherweise verzichtet man in Situationen mit insgesamt wenig 
Arbeitspeicher auf dynamische Speicherverwaltung - Stichworte wären da 
"Speicherfragmentierung", "Verwaltungsaufwand".

Die zweite Aufgabe erledigt man i.d.R. mit einem interruptgesteuerten 
Senden - d.h. der auszugebende Text wird in einen (globalen) Puffer 
eingetragen, und ein Interrupthandler, der von der UART ausgelöst wird, 
wenn sie ein Zeichen übertragen hat, überträgt quasi "im Hintergrund" 
den Inhalt dieses Puffers.

Man muss hierbei natürlich vor dem erneuten Befüllen des Puffers 
überprüfen, ob dieser wieder zur Verfügung steht, also der gesamte 
Inhalt versendet wurde.
Arbeitet man mit einem FIFO als Puffer-Organisation, können neue Zeichen 
in den Puffer eingetragen werden, sobald welche von der Interruptroutine 
"abgeräumt" wurden. Beim Eintragen ist also der Fifo-Füllstand zu 
überprüfen und gegebenenfalls zu warten.

von Stefen (Gast)


Lesenswert?

Hallo,

ich benutze jetzt einen Fifo aus Zeiger (char*).
1
int main()
2
{
3
putsUART("Hallo");
4
.
5
.
6
.
7
}
8
9
putsUART(char* str)
10
{
11
fifo[index].ptr = str; //Das Senden erfolgt in der ISR
12
index++;
13
.
14
.
15
.}

1- wird das funktionieren, oder werden die Daten irgendwann mal 
überschrieben(bei verschiedener String-Länge??
2- bis wann bleibt "Hallo" im Speicher, oder wann wird der Speicher von 
"Hallo" wieder frei?

Danke für die Infos

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Stefen wrote:
> Hallo,
>
> ich benutze jetzt einen Fifo aus Zeiger (char*).

Obacht.
Pointer in Datenstrukturen kann gefährlich sein.
So ein Pointer muss ja irgendwohin zeigen um nützlich
zu sein. Wenn das wohin er zeigt, aber out of scope
geht, dann hast du einen Pointer der in den Wald zeigt.

>
1
> int main()
2
> {
3
> putsUART("Hallo");
4
> .
5
> .
6
> .
7
> }
8
> 
9
> putsUART(char* str)
10
> {
11
> fifo[index].ptr = str; //Das Senden erfolgt in der ISR
12
> index++;
13
> .
14
> .
15
> .}
16
>
>
> 1- wird das funktionieren,

Das wird funktionieren. Und zwar deshalb, weil der
Scope eines String Literals das komplette Programm ist.
D.h. dieser konstante String wird beim Programmstart
erzeugt und überlebt, bis das Programm terminiert.

> oder werden die Daten irgendwann mal
> überschrieben(bei verschiedener String-Länge??

Da wird nichts überschrieben.

> 2- bis wann bleibt "Hallo" im Speicher, oder wann wird der Speicher von
> "Hallo" wieder frei?

Sollte jetzt auch schon klar sein.


Aber
das hier
1
void foo()
2
{
3
  char Text[] = "Test";
4
  putsUART( Text );
5
}

das kann und wird wahrscheinlich grauslich schief gehen.
Der Scope von Text ist die Funktion foo. Nachdem foo()
verlassen wurde, existiert die Variable Text nicht mehr.
Daran ändert auch nichts, dass innerhalb putsUART ein
Pointer auf diese Variable gespeichert wurde.

von Niels H. (monarch35)


Lesenswert?

Stefen wrote:

> putsUART("Hallo");

Ich meine irgendwo mal gelesen zu haben, das solch statische Strings vom 
Startup-Code ins SRAM kopiert werden, wenn sie vom Programmcode mit 
normalem char-pointer referenziert werden.

Eine andere Möglichkeit wäre, sie über das PROGMEM- Prefix Byteweise vom 
Flash ins SRAM zu holen.

Diese Info ist allerdings schon etwas älter; ich weiss nicht, ob sich da 
mitlerweile was getan hat...

von Stefen (Gast)


Lesenswert?

d.h. bei:
1
int main()
2
{
3
  while(1)
4
  {
5
    putsUART("messwert");
6
  }
7
.
8
.
9
.
10
}
wird der Speicher irgendwann mal voll?

von Niels H. (monarch35)


Lesenswert?

Stefen wrote:
> d.h. bei:
>
1
> int main()
2
> {
3
>   while(1)
4
>   {
5
>     putsUART("messwert");
6
>   }
7
> .
8
> .
9
> .
10
> }
11
>
> wird der Speicher irgendwann mal voll?

?!? wieso sollte?

von Karl H. (kbuchegg)


Lesenswert?

Stefen wrote:
> d.h. bei:
>
1
> int main()
2
> {
3
>   while(1)
4
>   {
5
>     putsUART("messwert");
6
>   }
7
> .
8
> .
9
> .
10
> }
11
>
> wird der Speicher irgendwann mal voll?

Meinst du das fifo Array. Ja sicher, irgendwann ist das
Array gefüllt.

Oder zielst du auf "messwert" ab?
"messwert" wird ja nur einmal 'erzeugt'. Nämlich dann wenn
das Programm hochkommt. Für das Programm existiert der
konstante String "messwert" ganz einfach sobald main()
die Kontrolle bekommt. Der ist schon da. Es gibt ihn
nur ein einziges mal.

Am Anfang schuf Gott, äh die Runtime, den String "messwert".
Und die Runtime sah, dass es gut war. Und der Programmierer
sprach: lass uns einen Pointer auf diesen String unendlich
oft im fifo Array ablegen. Doch das fifo Array murmelte
in seinen langen, weißen Bart: Ich kann nicht beliebig viele
Pointer aufnehmen. Mein Programmierer hat mich nur mit einer
begrenzten Kapazität ausgestattet. Aber ich befolge das
Gebot: Du sollst den Code deines Programmierers ausführen.

Da weinte die Runtime bitterlich und nachdem die Kapazität´
des Arrays erschöpft war geschahen seltsame Dinge.
So wurde am Ende der ersten Millisekunde
der 'Out of bounds'-Error erfunden. Und die Runtime sah nicht,
dass es nicht gut war, weil sie sich um Out of bounds Error
nicht kümmerte.

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.