Problem mit der Speicherverwaltung bei Funktionsrückgabe
-
C++ Programmierer schrieb:
.. welche vorteile hätte das, wenn ich es auf string umschreibe ..
Dass sie die Speicherverwaltung selbst machen

-
C++ Programmierer schrieb:
...welche vorteile hätte das, wenn ich es auf string umschreibe (außer, dass einige Standardfunktionen schon da wären)? ...
Ganz einfach: Du wärst z.B. Probleme wie das Obigen und das Folgende auf einen Schlag los:
C++ Programmierer schrieb:
...
...da ich in meinem ganzen Projekt solche Funktionen habe, die ganz gemein Speicher fressen, indem sie eben die Variable zurückgeben, anstatt sie mit zu übergeben :(....
Außerdem sind es mehr als "ein paar Standardfunktionen", die Du mit std::string verwenden kannst. Z.B. steht Dir die ganze STL zur Verfügung.
Insgesamt wirst Du Dich mehr auf die tatsächliche Arbeit des Programms konzentrieren können, weil Du Dich nicht mehr mit der Verwaltung von Zeichenketten und Speicher rumschlagen musst.Übrigens: Ich habe in Deinem Code nicht ein einziges C++-Konstrukt entdeckt - es ist lupenreines C. Kann man machen, aber wenn man C++ nutzen kann, vereinfacht es Vieles, wenn man es auch tut.
Nun aber zu Deiner ursprünglichen Frage:
C++ Programmierer schrieb:
char *Left(char *str, int length) { char *f; f = (char*)malloc(length); if (f==NULL) return ""; strncpy(f,str, length); f[length] = '\0'; return f; }...
(Hast Du schon gemerkt) Speicher wird angelegt und Du musst für die Freigabe sorgen. Prinzipiell ist die Frage: Wem soll der Speicher gehören ? Und eine übliche (wenn auch nicht zwingende) Antwort ist: Wer Speicher reserviert, muss ihn auch freigeben. Hier soll der Aufrufer diesen Speicher noch nutzten können, also muß er ihn auch bereitstellen:
void Left(char const *inStr, size_t inLength, char* outStr, size_t outLen ) { // Konsistenzchecks spare ich mir hier.... strncpy(outStr,inStr, inLength); } int main() { char outStackStr[100]; char *outHeapStr = new char[100]; char inStr[] = "Teste mich"; Left(inStr, strlen(inStr), &outStackStr, sizeof(outStackStr)); Left(inStr, strlen(inStr), outHeapStr, 100); // daran denken, dass exceptions fliegen können !! delete[] outHeapStr; }Hoppla ! Left() brauche ich ja gar nicht mehr - kann ja direkt strncpy() aufrufen !!!
(OK, war ja nur ein Beispiel)Alternativ der "häßliche-Entlein-Weg":
char* Left(char const *inStr, size_t inLength) { // Konsistenzchecks spare ich mir hier.... char outStr = new char[inLength]; strncpy(outStr,inStr, inLength); return outStr; } int main() { char *outHeapStr; char inStr[] = "Teste mich"; outHeapStr = Left(inStr, strlen(inStr), outHeapStr); // Stack-Variante geht jetzt nicht mehr ! // daran denken, dass exceptions fliegen können !! delete[] outHeapStr; }IMO handelt man sich damit mehr Probleme als Vorteile ein, aber gehen "tut es".
Ach ja: In C++ hieße das:
int main() { std::string outStr; std::string inStr = "Teste mich"; outStr = inStr; // oder outStr = inStr.substr(0,10); }Schon kürzer und übersichtlicher, oder ?
Gruß,
Simon2.
-
Ja, sehr viel schöner und übersichtlicher
Danke für die tolle Erläuterung!Also werde ich wohl mein Projekt auf die string Klasse umschreiben.
Ich weiß, dass ist eigentlich nicht die Foren Sektion dafür, aber wenn ich jetzt mit Strings aus der string Klasse Funktionen der Windows API aufrufen will muss ich doch buffer.c_str() aufrufen, und wenn die Größe von dem buffer verlangt wird sizeof(buffer), oder?
Gruß
Florian
-
Ja, c_str ist schon korrekt. Aber sizeof falsch. Die String-Klasse hat hat eine eigene size-Methode.
-
Ok, danke!
dann also buffer.max_size()
Gruß
Florian
-
C++ Programmierer schrieb:
...
Also werde ich wohl mein Projekt auf die string Klasse umschreiben....gute Entscheidung !

C++ Programmierer schrieb:
...
wenn ich jetzt mit Strings aus der string Klasse Funktionen der Windows API aufrufen will muss ich doch buffer.c_str() aufrufen...Jain !

- buffer.size() liefert die Anzahl der Zeichen im String zurück.
- c_str() liefert nur einen const-Zeiger ! Wenn die aufgerufene Funktion da auch reinschreiben will, kommst Du nicht drum herum, die Daten in ein char-Array zu kopieren. Ist aber auch kein Drama (s.u.).
string buffer = "Hier steht mein Kram drin"; // Nicht-Verändernde Funktion aufrufen: Easy: Nix zu tun changeNothingInCString(buffer.c_str(), buffer.size()); // hinkopieren (Annahme: Funktion hängt nichts an !) char * cStringBuffer = new char[buffer.size()]; buffer.copy(cStringBuffer, buffer.size()); // Verändernde Funktion aufrufen changeSomethingInCString(cStringBuffer, buffer.size()); // zurückkopieren buffer = cStringBuffer; delete[] cStringBuffer;Prinzipiell kannst Du die Kopiererei auch in eine eigene Wrapperfunktion auslegen - ob sich das lohnt, musst Du aber selbst entscheiden.
Gruß,
Simon2.
-
C++ Programmierer schrieb:
Ok, danke!
dann also buffer.max_size()
Gruß
FlorianVorweg: das std::string::max_size() vergiss einstweilen mal wieder. Die Funktion die die Länge des Strings zurückliefert ist std::string::size.
Und du solltest std::string nicht verwenden wenn du eine API Funktion aufrufen willst die einen non-const char Pointer will - dafür verwende lieber einen std::vector<char>.
-
Hallo,
mein erster Post
.Ich hätte mal eine Frage zu folgender Funktion:
string tuwas() { string s; s+="Hallo"; return s; } ... string g = tuwas(); ...Besteht hier bei string das gleiche Problem, wie wenn man es (wie oben) mit char * machen würde? Sollte man also auch bei Verwendung von "string" die Stringvariable vor Aufruf der Funktion anlegen, oder wird hier eine Kopie des strings zurückgegeben?
Mfg
-
Nein, bei string besteht das Problem nicht, weil der den Speicher selber verwaltet - und einen vernünftige Copy-Ctor, der sich um die Speicherverwaltung kümmert.
(aus Geschwindigkeitsgründen kann es trotzdem vorteilhaft sein, unnötige Kopien einzusparen)
-
Danke für die Info!
