char-Pointer und Delete
-
Hallo,
folgendes Codebeispiel gibt einen Assertion Failure:
in testdatei.h char *file1; in testdatei.cpp Application::Application(void){ file1 = "testname.xml"; } Application::~Application(void){ delete file1; }Ich würde das delte umgehen, indem ich einfach file1 = NULL; setze.
Wäre das so richtig?Und meine andere Frage:
Um delete zu verwenden, müssen die Variablen mit new instanziert werden.
Wenn ein char-Array direkt angelegt wird (wie oben), geschieht dies mit new oder nicht?Vielen Dank,
Phys1k3r
-
delete und new gehören zusammen. in diesem fall muss das delete also weg, weil der zeiger auf ein literal zeigt. das kann man logischerweise nicht löschen.
und
(void)schreibt man in c++ nicht als argumentliste.()reicht.
-
voidivoid schrieb:
delete und new gehören zusammen. in diesem fall muss das delete also weg, weil der zeiger auf ein literal zeigt. das kann man logischerweise nicht löschen.
Danke
und
(void)schreibt man in c++ nicht als argumentliste.()reicht.Haha, nach 1 Semester C-Einführung wo man jedes mal für ein vergessenes (void) einen Punkt Abzug bekommt, kann man fast gar nicht mehr anders...
-
ich würde dir sowieso zu std::string anstelle von char* raten. dann musst du auch nicht rätseln, wer wann wie löscht.
Haha, nach 1 Semester C-Einführung wo man jedes mal für ein vergessenes (void) einen Punkt Abzug bekommt, kann man fast gar nicht mehr anders...
in c++ macht man einiges anders als in c.
-
In C gibt's auch einen wesentlichen Unterschied zwischen () und (void), in C++ ist (void) dagegen äquivalent zu ()...
-
Hallo Phys1k3r,
Phys1k3r schrieb:
in testdatei.h char *file1;Ich nehme an, die Zeile steht innerhalb der Klassendefinition für Application. Dann würde hier nämlich eine nicht-statische Zeigervariable definiert.
Phys1k3r schrieb:
in testdatei.cpp Application::Application(void){ file1 = "testname.xml"; } Application::~Application(void){ delete file1; }Mach dir klar, was
file1 = "testname.xml";tatsächlich bedeutet und schalte mal die Compilerwarnstufe höher. Die rechte Seite ist ein konstantes, im statischen Speicherbereich lebendes char-Array. Bei der Zuweisung findet "array-to-pointer decay" statt und du speicherst in dem Zeiger file1 die Adresse des ersten Zeichens des String-Literals. Aus Gründen der C-Kompatibilität lässt dich ein C++ Compiler so etwas machen. Korrekterweise müsstest du aber file1 als "const char*" statt "char*" deklarieren, da es sich bei dem String-Literal um ein konstantes, im statischen Speicherbereich lebendes Array handelt.
Das delete im Destruktor ist gleich doppelt falsch. Das, worauf der Zeiger zeigt, hast du gar nicht per new angelegt, auch nicht ber new[]. Deswegen hat das delete da nichts zu suchen. Wenn du das char-Array selbst im Freispeicher pwe new[] angelegt hättest, hättest du auch delete[] statt delete benutzen müssen.
Wahrscheinlich hast du auch nicht die Dreierregel beachtet.
Mach es dir nicht so kompliziert. Schnapp dir ein schlaues C++ Buch und lerne die Sprache richtig. Vieles von dem, was du im C-Kurs gelernt hast, solltest du eigentlich beim Lernen von C++ ausblenden. Informiere dich über die drei Speicherbereiche (die es im Übrigen auch in C gibt): Automatischer Speicher (aka Stack), Statischer Speicher, Freispeicher (aka Heap). Zu jedem new gehört ein delete. Zu jedem new[] gehört ein delete[]. Wenn du meinst, new[]/delete[] häufig benutzen zu müssen, machst du etwas falsch; denn du kannst oft viel praktischere Dinge einsetzen, die dir die C++ Standardbibliothek anbietet. Der Typ einer Zeichenkettenvariablen heißt übrigens std::string und nicht char*. Genauso wie du in einer int-Variablen eine Zahl speichern kannst, kann std::string eine Zeichenkette (indirekt) speichertn. char* ist kein Typ für eine Zeichenkettenvariable, es ist ein Typ für Zeiger.
Phys1k3r schrieb:
Wenn ein char-Array direkt angelegt wird (wie oben), geschieht dies mit new oder nicht?
Nein. Zeichenkettenliterale leben im statischen Speicher. Das, was du per new und new[] anlegen kannst, lebt im Freispeicher.
-
krümelkacker schrieb:
Aus Gründen der C-Kompatibilität lässt dich ein C++ Compiler so etwas machen. Korrekterweise müsstest du aber file1 als "const char*" statt "char*" deklarieren, da es sich bei dem String-Literal um ein konstantes, im statischen Speicherbereich lebendes Array handelt.
In C++11 ist die Konvertierung in char* gar nicht mehr zulässig. 30 Jahre nach der Erfindung von const kann man schließlich erwarten, dass Code entsprechende geändert wurde

-
camper schrieb:
In C++11 ist die Konvertierung in char* gar nicht mehr zulässig.
Interessant!

-
camper schrieb:
krümelkacker schrieb:
Aus Gründen der C-Kompatibilität lässt dich ein C++ Compiler so etwas machen. Korrekterweise müsstest du aber file1 als "const char*" statt "char*" deklarieren, da es sich bei dem String-Literal um ein konstantes, im statischen Speicherbereich lebendes Array handelt.
In C++11 ist die Konvertierung in char* gar nicht mehr zulässig. 30 Jahre nach der Erfindung von const kann man schließlich erwarten, dass Code entsprechende geändert wurde

Notiz zur Kompabilität: GCC 4.8 (!) meldet nur eine deprecated-Warnung.
-
Sone schrieb:
camper schrieb:
krümelkacker schrieb:
Aus Gründen der C-Kompatibilität lässt dich ein C++ Compiler so etwas machen. Korrekterweise müsstest du aber file1 als "const char*" statt "char*" deklarieren, da es sich bei dem String-Literal um ein konstantes, im statischen Speicherbereich lebendes Array handelt.
In C++11 ist die Konvertierung in char* gar nicht mehr zulässig. 30 Jahre nach der Erfindung von const kann man schließlich erwarten, dass Code entsprechende geändert wurde

Notiz zur Kompabilität: GCC 4.8 (!) meldet nur eine deprecated-Warnung.
Bei mir auch. Hätte schwören können, deswegen schon mal einen richtigen Fehler bekommen zu haben. Jedenfalls ist der entsprechende Absatz (4.2/2) in C++11 nicht mehr vorhanden, Anhang C.1.1.
-
@Krümelkacker und der Rest
Danke für eure ausführlichen Antworten. Sie haben mich auf jeden Fall weitergebracht. Das Programm stürzt an dieser Stelle nicht mehr ab und ich habe auch verstanden, was dahinter steckt.Ich bin momentan am Debuggen eines Uniprojekts. Der Programmierer, der das Projekts geschrieben hat, ist ähnlich wie ich noch recht unerfahren. Der Code kam also gar nicht von mir, sondern wurde mir so (stark fehlerbehaftet) vorgesetzt.