Frage

Ich bin immer wieder über Rückkehr eine Stringliteral oder eine Zeichenfolge aus einer Funktion verwechselt. Ich wurde gesagt, dass es möglicherweise Speicherverlust sein, weil Sie nicht wissen, wenn der Speicher gelöscht werden?

Zum Beispiel in dem folgenden Code, wie foo() zu implementieren, um die Ausgabe des Codes zu machen ist „Hallo Welt“?

void foo (       )              // you can add parameters here.
{

}

int main ()
{
    char *c;
    foo (    );
    printf ("%s",c);
    return 0;
}

Auch wenn der Rückgabetyp foo() ist nicht leer, aber Sie können char* zurückkehren, was es sein sollte?

War es hilfreich?

Lösung

Ich gehe davon aus uns Haupt nicht ändern können. Um Ihr Programm Arbeiten ohne ein Leck, Sie brauchen etwas statischen Speicher zu haben:

void foo(char*& pC)  // reference
{
    static char theString[] = "thingadongdong";

    pC = theString;
}

Aber wirklich, das ist nicht sehr konventionell C ++ Code. Sie würden mit std::string und std::cout, so dass Sie nicht Haben , um Sorgen über Speicher:

std::string foo(void)
{
    return "better thingadongdong";
}

int main(void)
{
    // memory management is done
    std::cout << foo() << std::endl;
}

Wenn Sie sich fragen, ob etwas Bedarf manuell freigegeben werden, es wird falsch gemacht.

Andere Tipps

Da die alte Verwendung von char * ist veraltet, können Sie nicht einfach eine Zeichenfolge verwenden?

const char* func1 () {return "string literal";}

string func2 () {return "another string literal";}

Diese beiden gut funktionieren, ohne Compiler-Warnungen.

Allerdings

char* func3 () {return "yet another string literal";}

wird überhaupt nicht kompilieren. Auch wird

char* func4 () {return &"a ref to a string literal?";}

Stroustrup sagt in "The C ++ Programming Language" (Dritte Ausgabe):

"Ein Stringliteral statisch zugewiesen wird, so dass es sicher ist, eine aus einer Funktion zurückzukehren.

const char* error_message (int i)`
{
//...
return "range error";
}

Die Speicherhalte Bereichsfehler wird nicht nach einem Aufruf von Error_messages weggehen (). "

Also jedes Stringliteral in einem Programm in einem eigenen kleinen Stück Speicher zugeordnet ist, der für die Dauer des Programms dauert (das heißt statisch zugewiesen). Setzen Sie die const vor dem char * lässt den Compiler wissen, dass Sie beabsichtigen nicht (und kann nicht) verändern, dass kleine Stück des Stringliteral des Gedächtnisses, die gefährlich werden könnte, so dass sie trotz dieser Umwandlung dieser Zuweisung durchgehen lassen von Stringliteral zu char * veraltet.

Rückkehr stattdessen auf eine Zeichenfolge muss die Stringliteral in ein Objekt vom Typ String, Speicher kopieren, dass der Anrufer verantwortlich ist.

In beiden Fällen gibt es keine Speicherlecks: Jeder Stringliteral erhält seinen eigenen Teil des Speichers, der auf Programmende gereinigt wird; Rückkehr zum const char * gibt einen Zeiger auf ein Stück Speicher der wörtlichen (wissen Sie es nicht ändern können); und Rückkehr zu einer Zeichenfolge erstellt eine Kopie in ein String-Objekt in dem Anrufer vorhandenen Code, der vom Anrufer gereinigt wird.

Auch wenn es ein wenig hässlich Notation weisen scheint, ich bin zu raten sie den const char links * die preiswerte Alternative zu halten (einschließlich keine Kopien).

  

Ich bin immer verwirrt über Rückkehr eines Zeichenfolgenliteral oder eine Zeichenfolge aus einer Funktion.

Immutable, Zeichenkette

Wie ich es verstehe, sind Sie sicher, eine Stringliteral direkt zurück, wenn der Rückgabetyp const deklariert ist, zu erklären, dass die Zeichenfolge nicht geändert werden soll. Das heißt, Sie brauchen sich keine Sorgen über die Lebensdauer der Schnur / Speicherlecks.

Veränderliche, nicht-wörtliche Zeichenfolge

Wenn Sie jedoch einen String benötigen, dass Sie an Ort und Stelle ändern können, müssen Sie die Lebensdauer der Saite und die Größe der Speicherzuweisung betrachten, in dem sie gespeichert wird. Dies wird zu einem Problem, da Sie nicht mehr können ungeniert den gleichen Speicher zurückgeben für jeden Aufruf der Funktion enthalten Zeichenfolge, da eine vorherige Verwendung den Inhalt dieses Speichers verändert haben könnte, und / oder noch in Gebrauch sein kann. Daher ist ein neues Stück des Speichers muss die Zeichenfolge zurückgegeben halten zugeteilt.

Dies ist, wo das Potenzial für ein Leck auftritt, und wo die Wahl werden muss gemacht darüber, wo die Zuteilung und Freigabe erfolgen sollen. Sie könnten die Funktion haben, sich den Speicher und Zustand in der Dokumentation zuteilen, dass dies geschieht und schreiben vor, darin, dass der Anrufer die Speicher frei hat, wenn es nicht mehr benötigt wird (ein Leck zu verhindern). Dieses Mittel kann die Funktion einfach ein Zeichen zurückgeben *.

Die andere Option ist in einem gewissen Speicher an die Funktion zu übergeben, die von dem Anrufer zugewiesen wurden, und hat die Funktion Ort, um die Zeichenfolge innerhalb dieses Speichers. In diesem Fall sind beide die Anrufer zuordnet und ist verantwortlich für diesen Speicher zu befreien.

Schließlich habe ich erwähnt, dass die Größe des Speichers und String Notwendigkeit verwaltet werden, wenn eine veränderliche String verwenden. Die Zuteilung muss beide groß genug für die Zeichenfolge anfänglich durch die Funktion festgelegt und auch für jede geändert, die nach der Funktion vorgenommen werden, bevor der Speicher freigegeben wird. Geschieht dies nicht im Speicher richtig tun kann einen Pufferüberlauf verursachen, indem sie einen String zu langes Schreiben ursprünglich zugewiesen zu passen; Dies ist äußerst gefährlich für die Gesundheit und Sicherheit des Programms. Es kann Bugs und Sicherheitslücken verursacht, die extrem schwer zu erkennen sind. (Da die Quelle des Fehlers - der Überlauf - kann weit von den gesehenen Symptomen entfernt werden, wenn das Programm fehlschlägt)

So etwas wie folgt aus:

void foo(char ** pChar)
{
    // Make sure the string is shorter
    // than the buffer
    *pChar = new char[256];
    strcpy(*pChar,"Hello World!");
}

Dann rufen Sie es wie folgt aus:

foo(&c);

Wie im Kommentar erwähnt, seien Sie vorsichtig die Zeichenfolge Sie speichern kleiner ist als der Puffer, oder Sie werden einen ... Stack-Überlauf kommen! (Pun intended)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top