Dynamischer speicher



  • Hi Leute,
    ich habe folgendes Problem. Ich versuche eine eigene String Klassen zu schreiben, in dieser String Klasse gibt es einen char Pointer der zu einem char array wird. Soweit läuft alles wunderbar, jedoch so bald der Destruktor aufgerufen wird, bekomme ich eine Fehlermeldung:

    Unbehandelte Ausnahme bei 0x1022fb10 in 241.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00359000.

    Und dann mal kurz zu meinen wichtigsten Codeteilen

    //String.h
    #ifndef _STRING_H_
    #define _STRING_H_
    
    class String
    {
    	private:
    		char *str;
    		int len;
    	public:
    		String(void);
    		String(char *initString);
    		String (const String &str);
    		~String(void);
    		void print();
    		int getLength();
    		char getCharAt(unsigned int pos);
    		char* getStr();
    };
    
    #endif
    
    //String.cpp
    
    String::String(char *initString)
    {
    	len = strlen(initString);
    	str = new char[len+1];
    	strcpy(str, initString);
    }
    
    String::~String(void)
    {
    	delete[] str; 
    }
    
    void String::print()
    {
    		cout << str << endl;
    }
    

    Wenn ich im Destrucktor die delete Anweisung auskommentiere läuft alles ganz normal.
    Einer eine Idee ?



  • Auf den ersten Blick würde ich sagen, da fehlt der Zuweisungs-Operator (Stichwort "Rule of Three").

    (außerdem würde mich mal interessieren, wie dein Copy-Ctor aussieht)



  • Wie initialisierst Du denn den String ?

    Wennd der standardkonstruktor verwendet wird, initialisierst Du str ?



  • Ich würd' mal sagen, str zeigt auf einen falschen Speicherbereich 😮

    Ernsthaft, ich schätze mal dass du mit dem standard-konstruktor ohne Argumente initalisiert hast, und so dann den Speicher nicht initalisiert hast (?). Setz doch doch bei dem Standartkonstuktor str auf 0 und checke im Destruktor, ob str!=0 ist



  • delete und delete[] können NULL Pointer ab, die Prüfung kann also entfallen.



  • So ich versuch mal nach und nach auf die "Fragen" zu antworten 😉

    Mein Copy Konstucktor sieht wie folgt aus:

    String::String(const String &s)
    {
    	len = s.len;	
    	str = new char[len+1];
    	strcpy(str, s.str);
    }
    

    Mein Init für den String sieht wie folgt aus in der Funktion Main

    int main(int argc,char **argv)
    {
          String s;
    	s = String("WAU");
          system("pause");
    	return 0;
    }
    

    Und das andere klärt sich a mit meinen Auszug aus der Main 😉



  • Nachtrag 😉

    Mein Standartkonst. sieht wie folgt aus

    String::String(void)
    {
    	str = NULL;
    }
    


  • Wie gesagt, da fehlt der Zuweisungs-Operator (operator=). Du hast dort zwei String-Objekte angelegt (s und den temporären String("Wau")) und weißt diese einander zu. Der vorgegebene op= kopiert nur die direkten Datenelemente (also len und str), aber nicht das dahinterliegende char-Array, so daß nach der Zuweisung beide Objekte den selben Speicher verwalten.
    Anschließend rufen beide Objekte delete[] für diesen Speicher auf (der temporäre String am Ende der Zuweisung, s hinter dem return 0) - und schon kracht es, weil du Speicher freigeben willst, der dir gar nicht (mehr) gehört.





  • @CStoll

    Ich dachte dieses Problem wird durch den CopyKon. gelöst oder habe ich da was falsch verstanden ? Weil der soll doch grade so eine Zuweisung ermöglichen.



  • Schau Dir mal den Artikel von Hume an (siehe oben)



  • Wusler schrieb:

    Ich dachte dieses Problem wird durch den CopyKon. gelöst oder habe ich da was falsch verstanden ? Weil der soll doch grade so eine Zuweisung ermöglichen.

    Nein, eben nicht. Der Copy-Ctor wird nur für Direkte Initialisierungen (z.B. "String s = String("Wau");") verwendet, für Zuweisungen gibt es einen eigenen Operator (der muß sich schließlich auch darum kümmern, die alten Daten deines Strings wieder freizugeben).



  • Ich bin momentan nich so fit in c++, darum frag ich einfach mal:

    Gibt es keine fertigen guten String Klassen ? (Schon beim Standard dabei?)



  • std::string



  • Danke dir CStoll, dass ergibt natürlich Sinn 👍
    Und ja diese Stringklasse ist mir bekannt, aber ich darf meine eigene Stringkalssen schreiben, weil das unser Dozent so will



  • Die Antwort war auch eher für xindon gedacht 🙂



  • Knuddlbaer schrieb:

    std::string

    std:string ist keine Klasse - nur ein typedef 🕶



  • Man kann auch jemanden, der frisch mit C++ angefangen hat, den Typedef auflösen und ihn dann damit alleine lassen.

    Ich denke nicht, das ein

    basic_string<char>
    

    die richtige Antwort auf die Frage ist.

    Eigentlich müsse man ja, um exakt zu sein,

    template <
       class CharType,
       class Traits=char_traits<CharType>, 
       class Allocator=allocator<CharType> 
    >
    class basic_string
    

    noch mit angeben.

    Aber drehen wir das doch mal um:

    Warum ist der Typedef keine Klasse ? So ist es doch ein "stellvertretender" Ausdruck für die Klasse basic_string<char>


Anmelden zum Antworten