[C/C++]String korrekt übergeben

Hi Programmers!

Wie definiere ich eine Funktion mit Rückgabewert string (char[]) korrekt? Folgendes führt immer zum Absturz:

aufruf mit:
text = errorText(errorcode);

Funktion:
char *errorText(int errorcode)
{
char text[] = „“;
strcpy(text,„BlaBla“);
return text;
}

Was ist daran falsch?

Thanx für Eure Tipps!

Lex.

Moin,

Wie definiere ich eine Funktion mit Rückgabewert string
(char[]) korrekt?

Gibt es da eine Standardlösung?

Was ist daran falsch?

Mehreres.
char text[] = „“;
Damit hast Du nur Platz für ein Zeichen, ‚\0‘ erstellt. Dieser Platz wird außerdem wieder freigegeben, wenn Du die Funktion verläßt.

So geht’s:

#define BufSize 1024

char target[BufSize];

errorText(target, code);

Und:
char* errorText(char* target, int errorcode)
{
strncpy(target, „BlaBla“, BufSize);
return target;
}

Thorsten

Hi Lexus :wink:))

aufruf mit:
text = errorText(errorcode);

Ist ok !

Funktion:
char *errorText(int errorcode)
{
char text[] = „“;
strcpy(text,„BlaBla“);
return text;
}

Was ist daran falsch?

Das sind zwei wesentliche Fehler dirn:

(1) Mittels

char text[]= „“;

legst du auf dem Stack einen Speicherbereich von strlen(text)+1 Bytes an. Plus 1 deswegen, weil eine Zeichenkette ja mit einem Nullbyte abgeschlossen wird. In deinem Fall (leerer String) wird also 1 Byte reserviert und dieses wird mit einer Null initialisiert. Der C-Compiler interpretiert „text“ dann als Zeiger auf den Beginn dieses 1-Byte-Speicherbereichs. Mit

strcpy(text,„BlaBla“);

kopierst du jetzt den String „BlaBla“ in diesen Speicherbereich. Das erste ‚B‘ findet darin Platz, aber schon das erste ‚l‘ sprengt den reservierten Speicherplatz. Normalerweise wird das mit einem „segmentation fault“ oder (unter Windows) mit einer „ungültigen Seite“ geahndet!

(2) Mittels

char text[]= „“;

definierst du eine automatisches Array. Dieses wird angelegt, wenn du in den Funktionscode eintrittst und es wird zerstört, wenn du den Funktionscode verlässt. Mit anderen Worten, mit

return text;

überigbst du zwar die Startadresse deines Speicherbereichs, aber dieser ist ja beim Verlassen der Funktion errorText() zerstört worden. Der Zeiger „text“ zeigt außerhalb von errorText() also ins Nichts!

Eine korrekte Version von errorText() könnte z.B. so aussehen:

#include /\* Hier ist malloc() deklariert \*/

char \*errorText(int errorcode) {
 char \*text= malloc(strlen("BlaBla")+1);
 strcpy(text,"BlaBla");
 return text; }

Hier wird mittels malloc() ein Speicherbereich von passender Länge definiert und seine Startadresse wird „text“ zugewiesen. Jetzt klappt auch der strcpy()-Aufruf. Und der Speicherbereich bleibt auch nach Verlassen von errorText() gültig. Ja du musst ihn außerhalb von errorText() sogar selber zerstören, etwa mit:

free(text);

Ich vermute jedoch, dass du einfach nur einen Text zu einer Fehlernummer zurückgeben möchtest. Das würde ich so programmieren:

char \*errorText(int nr) {
 char \*meldungen[]= {
 "Sie benutzen Windows, Fehler Nr. 0",
 "Sie haben einen Pentium-Prozessor, Fehler Nr. 1",
 "So geht's auch nicht, Fehler Nr. 2",
 "User ist zu dumm, Fehler Nr. 3" };

 return meldungen[nr]; }

Das funktioniert deswegen, weil alle konstanten Zeichenketten (also alle Fehlermeldungen) am Ende des Programms abgelegt werden und mit „char *meldungen[]“ ein Array von Zeigern auf char definiert wird, in dem die Startadressen dieser konstanten Zeichenketten abgelegt werden …

Du musst mal sehen, für welche Lösung du dich entscheidest. Ich hoffe, dir geholfen zu haben. Wenn du noch Fragen hast, kannst du dich gerne bei mir melden …

cu Stefan.

aufruf mit:
text = errorText(errorcode);

Funktion:
char *errorText(int errorcode)
{
char text[] = „“;
strcpy(text,„BlaBla“);
return text;
}

Erstens erzeugst du mit dem

char text[] = "";

einen Buffer von der Größe eines char, was aber nicht für „blabla“ ausreicht, dafür bräuchtest du 7 (6 Buchstaben und eine ‚\0‘).

Zweitens erzeugst du den buffer lokal in deiner Funktion, der Speicher wird am Ende der Funktion wieder freigegeben, du erhältst einen Pointer ins nichts.

Damit der Speicher Bestand hat müsstest du ihn c-mässig mit malloc() anlegen oder mit dem C++ new-Operator. Beschäftige dich noch einma genauer mit der Speicherverwaltung, das sind ganz wichtige Grundlagen, die die hier anscheinend nciht vertraut sind.

Mfg Bruno

(unter Windows) mit einer „ungültigen Seite“ geahndet!

was ist das? hab ich noch nie gesehen
Bei mir heisst das „Schutzverletzung“…

Hi Bruno :wink:))

Bei mir heißt es „… verursachte eine Schutzverletung durch eine ungültige Seite“ …

Kann aber sein, dass das an Visual C++ Enterprise liegt. Da sind die Debug-Funktionen sehr ausgebaut. Es gibt sehr viele Informationen beim Auftreten eines Bugs … Das nervt manchmal sogar, wenn plötzlich irgendein Assembler-Code von System-DLLs erscheint :wink:))

cu Stefan.

Hallo Lexus

Was meine Vorredner geschrieben haben ist richtig, es gibt aber noch eine andere Variante:

Funktion:
char *errorText(int errorcode)
{
static char text[1024] = „“;
strcpy(text,„BlaBla“);
return text;
}

Durch static kannst du erreichen, dass die Variable nicht auf dem Stack abgelegt wird, sondern im normalen Datenbereich, also immer existiert wenn das Programm läuft.

Das ganze entspricht der Lösung von Thorsten:

#define BufSize 1024
char target[BufSize];

char* errorText(char* target, int errorcode)
{
strncpy(target, „BlaBla“, BufSize);
return target;
}

mit dem kleinen unterschied, dass die verwendete Variable (target) nicht von einer anderen Stelle im Programm „sichtbar“ ist.

MfG Peter(TOO)

SORRY, stefan, …
…ich habe aus versehen auf die FALSCHE BEWERTUNG getippt.
UND DAS -nach murphy- bei einem der BESTEN artikel die ich
je gelesen habe. es tut mir leid.
DER ARTIKEL VERDIENT EINE 1++

gruss -besserunggelobendundmeaculpasagend-
digi

Hi Diggi :wink:))

Danke für die Blumen :wink:))
Aber die seit neustem eingeführte Bewertung von Artikeln halte ich nicht für sinnvoll. Mir ist es auch relativ egal, wie meine Artikel bewertet werden. Es geht darum, dass die Leute eine vernünftige Antwort auf ihre Fragen kriegen. Ich mache mir vielmehr Sorgen, dass jetzt andere Leute abgeschreckt werden, eine Antwort zu posten, aus Angst vor einer schlechten Bewertung. Ich für meinen Teil tue einfach so, als wäre die Bewertung nicht da, ich bewerte keine Artikel und ich ignoriere die Bewertung meiner eignen Artikel …
Trotzdem nochmal Danke für das Lob :wink:))

cu Stefan.

Hi Peter :wink:))

…, es gibt aber noch eine andere Variante:

Funktion:
char *errorText(int errorcode)
{
static char text[1024] = „“;
strcpy(text,„BlaBla“);
return text;
}

Das funktioniert sicherlich. Eine static-Variable innerhalb einer Funktion wird vom Compiler ja wie eine globale Variable behandelt, die nur innerhalb der Funktion angesprochen werden kann. Das ist aber genau das Problem bei dieser Variante. Wenn du zwei wiederholte Aufrufe der Funktion startest, etwa

char *text1= errorText(2);
char *text2= errorText(3);

dann liefert der Zeiger „text1“ nicht (wie erwartet) den Text zu Fehler Nummer 2, sondern genau wie „text2“ den Text zu Fehler Nummer 3. Denn „text1“ und „text2“ zeigen ja beide auf die selbe „globale“ Variable und deren Inhalt wird durch den letzten Aufruf von errorText() bestimmt! Daher würde ich von dieser Methode abraten, hier sind unerwünschte Seiteneffekte im wahrsten Sinne des Wortes programmiert :wink:))

cu Stefan.

Hi stefan, … auch nachtarbeiter?.. :smile:
du hast recht mit der ‚bewertung‘.
wie kann man das messen, woran?
alles gute - digi

Thanx a Lot! (o.T)
Hi Programmers!

Hey, ich danke Euch vielmals für alle diese Antworten! Da hätte ich natürlich auch selbst drauf kommen können… aber die Experten wissens natürlich besser!

Herzlichen Dank nochmals, ich hofe, dass ich auch mal dem einen oder anderen helfen kann!

Gruss

Lex.

Hallo Stefan

Das funktioniert sicherlich. Eine static-Variable innerhalb
einer Funktion wird vom Compiler ja wie eine globale Variable
behandelt, die nur innerhalb der Funktion angesprochen werden
kann. Das ist aber genau das Problem bei dieser Variante. Wenn
du zwei wiederholte Aufrufe der Funktion startest, etwa

char *text1= errorText(2);
char *text2= errorText(3);

dann liefert der Zeiger „text1“ nicht (wie erwartet) den Text
zu Fehler Nummer 2, sondern genau wie „text2“ den Text zu
Fehler Nummer 3. Denn „text1“ und „text2“ zeigen ja beide auf
die selbe „globale“ Variable und deren Inhalt wird durch den
letzten Aufruf von errorText() bestimmt! Daher würde ich von
dieser Methode abraten, hier sind unerwünschte Seiteneffekte
im wahrsten Sinne des Wortes programmiert :wink:))

Ich weiss schon, dass „meine“ Version nicht reentrant ist, aber ich habe mich ja auch ausdrücklich auf die Lösung von Thorsten bezogen !

P.S. Schau dir doch mal die Funktion „strerror()“ mal genauer an !!

MfG Peter(TOO)