mikrocontroller.net

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


Autor: Stefen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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???
char* ar;
int tmp = 0;
tmp = sprintf(ar,"test"); // tmp ist dann 4

Gruß

Autor: Thomas B. (detritus)
Datum:

Bewertung
0 lesenswert
nicht 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):
char ar [5];
int tmp = 0;
tmp = sprintf(&ar[0],"test"); // tmp ist dann 4
oder 
tmp = sprintf(ar,"test"); // tmp ist dann 4

Autor: Patrick K (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beispielsyntax:
char mystring[20];

long mylong;

 

mylong=1234;

sprintf(mystring,"<%lu>",mylong);

// mystring now has:

//      < 1 2 3 4 > \0

Autor: Stefen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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???

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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??

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich benutze jetzt einen Fifo aus Zeiger (char*).
int main()
{
putsUART("Hallo");
.
.
.
}

putsUART(char* str)
{
fifo[index].ptr = str; //Das Senden erfolgt in der ISR
index++;
.
.
.}

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ß

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

>
> int main()
> {
> putsUART("Hallo");
> .
> .
> .
> }
> 
> putsUART(char* str)
> {
> fifo[index].ptr = str; //Das Senden erfolgt in der ISR
> index++;
> .
> .
> .}
> 
>
> 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
void foo()
{
  char Text[] = "Test";
  putsUART( Text );
}

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.

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Stefen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
d.h. bei:
int main()
{
  while(1)
  {
    putsUART("messwert");
  }
.
.
.
}
wird der Speicher irgendwann mal voll?

Autor: Niels Hüsken (monarch35)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefen wrote:
> d.h. bei:
>
> int main()
> {
>   while(1)
>   {
>     putsUART("messwert");
>   }
> .
> .
> .
> }
> 
> wird der Speicher irgendwann mal voll?

?!? wieso sollte?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefen wrote:
> d.h. bei:
>
> int main()
> {
>   while(1)
>   {
>     putsUART("messwert");
>   }
> .
> .
> .
> }
> 
> 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.