4 Stimmen

Was ist an diesem Code falsch?

int main()
{
    char *name = new char[7];
    name = "Dolphin";
    cout << "Your name is : " << name <<endl;
    delete [] name;
}

Warum beschwert sich der VC++-Compiler nicht?

10 Stimmen

Sie sollten Folgendes verwenden std::string die solche Dinge zulässt.

4 Stimmen

Er beschwert sich nicht, weil bei C/C++-Programmierern davon ausgegangen wird, dass sie wissen, was sie tun. Auf "name" irgendwo anders hinzuweisen ist völlig legal. Obwohl ich in diesem Fall erwarten würde, dass GCC eine Warnung ausgibt, weil Sie einen (char *) Zeiger für den Zugriff auf den konstanten Abschnitt verwenden. Ich kenne mich mit VC++ nicht aus. Wenn Sie nichts sagen, gibt main() 0 zurück.

1 Stimmen

Warum sollte sie sich beschweren? Sie tun nichts Illegales, soweit es den Compiler betrifft. Compiler sind nicht telepathisch, sie wissen nicht, was Sie tun wollten, im Gegensatz zu dem, was Sie tatsächlich getan haben.

14voto

djna Punkte 53789

Sie haben hier zwei Fragen:

Erstens: Was ist falsch am Code? Nun ...

Wenn Sie "Dolphin" dem Namen zuweisen, kopieren Sie nicht in das zugewiesene Array, sondern passen den Zeiger so an, dass er auf ein Stringliteral zeigt. Später versuchen Sie zu löschen, worauf der Zeiger zeigt. Ich würde erwarten, dass dies in einigen Umgebungen schrecklich abstürzen wird.

Wenn Sie wirklich eine Kopie der "Dolphin"-Zeichen wollen, schauen Sie sich strncpy() an, aber wie bereits erwähnt, brauchen Sie auch ein Leerzeichen für die Null.

Zweitens, warum dieser bestimmte Compiler Sie nicht warnt, dass die Zuweisung potenziell ist: Das ist etwas schwieriger. [Die Frage ist, ob dieser Compiler ein String-Literal als "Zeiger auf const char" oder als "Zeiger auf char" behandelt.

Wenn es der erste Fall wäre, würde ich einen Fehler erwarten. Bis etwa 2004 war C++ konsistent mit C bei der Behandlung Literale als Zeiger auf char, und damit die Zuordnung wäre zulässig. Die Frage, die sich Ihnen stellt, ist also, mit welcher Version der Spezifikationen Sie arbeiten, und das könnte von der Version von VC++ abhängen, die Sie verwenden, und auch von den Compileroptionen, die Sie gewählt haben.

A MSDN C++ Referenz zeigt an, dass VC++ String-Literale als nicht konstant behandelt. Ich überlasse es den VC++-Gurus, weitere Kommentare abzugeben.

3voto

Pointy Punkte 387467

Das Problem ist, dass Sie versuchen delete eine Zeichenkettenkonstante, "Dolphin".

2voto

laura Punkte 7152
  1. Sie müssen 8 Zeichen zuweisen
  2. Sie können ein String-Literal nicht auf diese Weise zuweisen. Verwenden Sie entweder const char *name = "Dolphin" (keine Zuweisung erforderlich!) und NICHT LÖSCHEN oder verwenden strcpy um den Text in den neu zugewiesenen Bereich zu kopieren - den Sie später löschen.

Sie können ein String-Literal ("Dolphin"), das sich im Nur-Lese-Speicher befindet, nicht löschen. Auch in diesem Sinne - wenn Sie schreiben name = "Dolphin" Sie weisen den Zeiger neu zu, was bedeutet, dass der ursprünglich zugewiesene Speicher verloren geht.

1voto

Michał Trybus Punkte 10906
  1. Sie haben nicht berücksichtigt iostream und erklärte, dass Sie using namespace std; während Sie cout und cin verwenden, die darin definiert sind,
  2. Sie haben ein Speicherleck in Zeile 4. name auf einen Speicher verweist, wenn Sie ein Zeichenfolgenliteral zuweisen, weisen Sie tatsächlich einen Zeiger darauf zu und verlieren so den Zeiger auf die 7 zuvor zugewiesenen Bytes,
  3. In der 6. Zeile versuchen Sie, einen Speicherblock freizugeben, der sich vermutlich im Nur-Lese-Speicher befindet, da er vom Compiler aus einem String-Literal erstellt wurde. Nach dem Standard ist es nicht erlaubt, solchen Speicher freizugeben.

Zwei korrekte Vorgehensweisen wären hier zu nennen:

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    char *name = new char[8];
    strcpy(name, "Dolphin");
    cout << "Your name is : " << name <<endl;
    delete [] name;
    return 0;
}

Denken Sie daran, dass Sie zum Speichern von "Dolphin" 8 Bytes benötigen, wobei 1 Byte für das NUL-Zeichen vorgesehen ist. Die zweite Version (mehr C++):

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string name = "Dolphin";
    cout << "Your name is : " << name <<endl;
    return 0;
}

Und diese braucht nicht gelöscht zu werden.

Der Grund, warum sich der Compiler nicht beschwert, ist einfach, dass der Compiler nicht für Sie auf Speicherlecks prüft. Dafür gibt es andere Programme, zum Beispiel valgrind. Der Compiler wird sich auch nicht über das Löschen des Speichers des String-Literales beschweren, weil er nicht analysiert, was Sie mit dem Zeiger gemacht haben, seit Sie ihm die Adresse eines String-Literales zugewiesen haben, so dass er nicht wissen kann, dass er sich seither nicht geändert hat.

1voto

René Nyffenegger Punkte 37584
const char* name;

ist ausreichend. Wenn Sie dem Namen "Dolphin" zuweisen, ändert sich der Wert des Zeigers. Schließlich wird der delete[] name ist falsch. Es wird versucht, die Konstante char* "Dolphin" zu löschen, die nicht auf dem Heap alloziert ist.

Der gesamte Code könnte also lauten

int main()
{
    const char *name;
    name = "Dolphin";
    cout << "Your name is : " << name <<endl;
}

Der Compiler beschwert sich nicht, da Ihr Code nicht gegen die Grammatik von C++ verstößt

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X