Autor |
Beitrag |
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 24.08.17 10:20
- Nachträglich durch die Entwickler-Ecke gelöscht -
|
|
Th69
Beiträge: 4777
Erhaltene Danke: 1054
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 24.08.17 11:14
OK, ich dachte, das sei offensichtlich.
Ich kommentiere ihn deshalb mal:
C++-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| char* cNeu = new char[3]; cNeu = "Neu"; printf("%s", cNeu); delete(cNeu); char* cAlt = (char*)malloc(3 * sizeof(char)); cAlt = "Alt"; printf("%s", cAlt); free(cAlt); |
Wahrscheinlich meintest du in Zeile 2 (und [jetzt] 10):
C++-Quelltext 1: 2: 3:
| strncpy(cNeu, "Neu", 3); strncpy(cAlt, "Alt", 3); |
d.h. du schreibst in den mittels new/ malloc allozierten Speicherbereich etwas rein (s. strncpy).
Ergänzung: Bedenke, daß aber hier der String dann nicht null-terminiert ist, d.h. die Ausgaben mittels cout oder printf dann ebenso UB sind!
|
|
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 24.08.17 11:43
- Nachträglich durch die Entwickler-Ecke gelöscht -
|
|
hydemarie
Beiträge: 481
Erhaltene Danke: 51
|
Verfasst: Do 24.08.17 11:59
Frühlingsrolle hat folgendes geschrieben : | Da müsste man mit strncpy() arbeiten. |
Je nach System. Der C11-Standard und Microsoft empfehlen strncpy_s, ältere C-Standards strncpy(), unter bestimmten Systemen mit bestimmten C-Standardbibliotheken bietet sich vielleicht eher strlcpy() an. Und so weiter.
Ja, aber cNeu ist hinterher immer noch NULL.
|
|
Th69
Beiträge: 4777
Erhaltene Danke: 1054
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 24.08.17 13:29
C++-Quelltext
Dies gibt einen Compilerfehler (oder zumindestens eine Warnung): Ideone-Code, sofern cNeu weiterhin als char * deklariert ist, denn *cNeu entspricht ja cNeu[0], d.h. nur der Wert der Speicheradresse (also hier ein einzelnes Zeichen ( char)).
----------------
hydemarie hat folgendes geschrieben: | Ja, aber cNeu ist hinterher immer noch NULL. |
Was meinst du damit??? Wie kommst du auf NULL?
|
|
hydemarie
Beiträge: 481
Erhaltene Danke: 51
|
Verfasst: Do 24.08.17 13:42
Gegenfrage: Mit welchem Wert (nicht: Typ) ist cNeu denn initialisiert?
|
|
Th69
Beiträge: 4777
Erhaltene Danke: 1054
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 24.08.17 13:53
Wir reden (bzw. schreiben) hier doch von:
C++-Quelltext 1:
| char* cNeu = new char[3]; |
also hat cNeu wohl einen anderen Wert als NULL (und sollte new keinen Speicher mehr allozieren können, dann gibt es eine bad_alloc Exception).
|
|
hydemarie
Beiträge: 481
Erhaltene Danke: 51
|
Verfasst: Do 24.08.17 14:04
Th69 hat folgendes geschrieben : | also hat cNeu wohl einen anderen Wert als NULL |
Nämlich?
Was ist denn der Standardwert eines char?
|
|
Th69
Beiträge: 4777
Erhaltene Danke: 1054
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 24.08.17 14:12
Ich verstehe dich leider immer noch nicht. Bitte poste nochmals den gesamten Code, auf den du dich beziehst.
|
|
hydemarie
Beiträge: 481
Erhaltene Danke: 51
|
Verfasst: Do 24.08.17 14:20
Du behauptest, cNeu habe einen anderen Wert als NULL. Welchen hat er denn deiner Meinung nach? Das war doch eine eigentlich ganz einfach formulierte Frage.
Nachtrag:
C++-Quelltext 1:
| printf("cNeu ist %s\n", cNeu); |
|
|
Th69
Beiträge: 4777
Erhaltene Danke: 1054
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 24.08.17 14:36
cNeu ist ein Zeiger, d.h. es enthält eine Adresse:
C++-Quelltext
Wenn du
C++-Quelltext 1:
| printf("cNeu ist %s\n", cNeu); |
ausgibst, dann gibt du den Inhalt als nullterminierten String aus, auf den cNeu zeigt (das ist etwas ganz anderes - und NULL wird dann auch nicht ausgegeben).
|
|
hydemarie
Beiträge: 481
Erhaltene Danke: 51
|
Verfasst: Do 24.08.17 14:44
Du hast meine Frage nicht beantwortet.
Der Wert, der an der Adresse, auf die der Zeiger zeigt, steht, ist was , wenn nicht NULL?
Was ist der Standardwert eines nicht initialisierten char*?
Th69 hat folgendes geschrieben : | NULL wird dann auch nicht ausgegeben). |
Das liegt daran, dass NULL nicht ausgegeben werden kann. Auf ideone steht da stattdessen (null) ...
Nachtrag:
Die ursprüngliche Frage war ja:
C++-Quelltext
Ich unterstelle, dass das so gemeint war, dass hinterher in cNeu "Neu" drinsteht. @Frühlingsrolle mag mich diesbezüglich korrigieren. Die Ausgabe von cNeu ist und bleibt hinterher aber "leer".
|
|
Th69
Beiträge: 4777
Erhaltene Danke: 1054
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 24.08.17 14:53
Das ist UB, denn bei einem nicht-initialisierten Zeiger weiß man ja gar nicht, worauf der Zeiger zeigt (irgendeine beliebige Speicheradresse):
C++-Quelltext 1: 2: 3: 4: 5: 6:
| int main() { char *cNeu; printf("%x\n", cNeu); printf("%s\n", cNeu); } |
(Im Debug-Modus werden diese [lokalen Variablen] zwar von einigen Compilern mit 0 initialisiert, aber spätestens im Release-Modus führst dies zu undefinertem Verhalten).
Nachtrag:
Dein letzter Satz ist jetzt aber erst recht widersprüchlich:
Wenn da "Neu" drinsteht (also wenn man es korrekt z.B. mittels strncpy oder strcpy kopiert), dann wird auch "Neu" ausgegeben!
Warum sollte der vorher zugewiesene Zeiger auf einem mal NULL sein???
Zuletzt bearbeitet von Th69 am Do 24.08.17 14:59, insgesamt 1-mal bearbeitet
Für diesen Beitrag haben gedankt: hydemarie
|
|
hydemarie
Beiträge: 481
Erhaltene Danke: 51
|
Verfasst: Do 24.08.17 14:56
Th69 hat folgendes geschrieben : | Das ist UB, denn bei einem nicht-initialisierten Zeiger weiß man ja gar nicht, worauf der Zeiger zeigt |
Und wenn du ihn ausgibst, ist das Verhalten in jedem mir bekannten Compiler gleich: Da steht dann "nichts" drin.
(N.b.: calloc() ist in vielen Fällen die deutlich bessere Wahl, wenn man sich über die Werte nicht ganz sicher ist.)
|
|
Th69
Beiträge: 4777
Erhaltene Danke: 1054
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 24.08.17 15:11
Hier nochmal als Ideone-Code -> Runtime error!
|
|
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 24.08.17 17:22
- Nachträglich durch die Entwickler-Ecke gelöscht -
Für diesen Beitrag haben gedankt: hydemarie
|
|
tomycat
Beiträge: 265
Erhaltene Danke: 1
|
Verfasst: Fr 25.08.17 08:16
|
|
hydemarie
Beiträge: 481
Erhaltene Danke: 51
|
Verfasst: Fr 25.08.17 09:20
Du machst den Speicher frei, sobald du ihn beziehungsweise den Wert nicht mehr brauchst.
Am Ende würde auch gehen, aber dann müsstest du realloc() (Neubelegen noch reservierten Speichers) für jede Zeile nutzen. Vorteil: du müsstest nur noch einmal aufräumen. Ist aber gefährlicher, was mögliche Memleaks, also auch nach dem Programmende noch belegten Speicher, betrifft, zum Beispiel bei Fehlern in der Schleife.
Für diesen Beitrag haben gedankt: tomycat
|
|
tomycat
Beiträge: 265
Erhaltene Danke: 1
|
Verfasst: Fr 25.08.17 16:10
ok,
Zeile 2: Wenn textfile Null, dann bricht die Schleife ab.
Zeile 3: Es wird Untersucht ob ein \n in textfile vorhanden ist, das wird in nextline gespeichert.
Zeile 4: ist nextline wahr, dann kommt es zu einer Subtaktion, ähh das geht ?!? Zeichenlänge wird berechnet
Zeile 5: Dann reserviere ich mir einen Speicherplatz für linelenth und weise Ihn dem temp_str zu, richtig?
Wird die If Abfrage ausgeführt, bei 10 Zeilen, 10 mal ausgeführt. Dann wird doch immer der Speicher wieder freigegeben?
|
|
hydemarie
Beiträge: 481
Erhaltene Danke: 51
|
Verfasst: Fr 25.08.17 16:18
Das ist so richtig, ja.
Für diesen Beitrag haben gedankt: tomycat
|
|