Damage after normal Block (finde aber meinen Fehler nicht)



  • Hallo Leute,
    habe da ein kleines Problem mit dem folgenden Programm. Es ist unter Visual C++ 6.0 geschrieben und beim Beenden des Programms erhalte ich folgenden Fehler: Damage after normal Block. Laut Google liegt es daran, das ein const-Speicherbereich überschrieben wird. Ich finde aber meinen Fehler nicht. Vielleicht könnt ihr mir ja helfen. Mach C++ leider auch nicht ganz so lange. Ist aber sehr wichtig. Danke schon mal an Euch alle.

    Die cpp ist:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <climits>
    #include <assert.h>
    #include <iostream>
    using namespace std;
    
    /*--- #includes der Form "..." ---------------------------------------*/
    #include "per4.hpp"
    /*--- #define-Konstanten und Makros ----------------------------------*/
    /*--- Datentypen (typedef) -------------------------------------------*/
    /*--- Globale Konstanten (extern) ------------------------------------*/
    /*--- Globale Variablen (extern) -------------------------------------*/
    /*--- Prototypen globaler Funktionen ---------------------------------*/
    int main(void)
    {
       const Person father("Karl", 55), mother("Brigitte", 51);
       Person myself, another;
       cout << "father = " << father;
       cout << "mother = " << mother;
       for (;;)
       {
          cout << "Bitte Vorname und Alter (durch Leerzeichen getrennt) eingeben:\n";
          if (cin >> myself)
             break;
          cout << "Eingabefehler! Bitte wiederholen...\n";
          cin.clear();
          cin.ignore(INT_MAX, '\n');
       }
       cout << "myself = " << myself;
    
       Person son(father); // (vom Compiler erzeugter?) Kopier-Konstruktor
       cout << "son = " << son;
       son.setName("Ludwig-Adalbert");
       son.setAge(2);
       cout << "son = " << son;
       another = mother;   // (vom Compiler erzeugter?) Zuweisungsoperator
       cout << "another = " << another;
       // nicht sinnvoll, aber muss moeglich sein
       son = son;
       cout << "son = " << son;
       // nicht sinnvoll, aber muss moeglich sein
       son.setName(son.getName());
       cout << "son = " << son;
    }
    

    Und die hpp lautet:

    #ifndef PER4_HPP
    #define PER4_HPP
    
    class Person
    {
    private:
    	char *pName;
    	int age;
    public:
    	void setName(const char *personname);
    	void setAge(int personalter);
    	const char *getName() const;
    	int getAge() const;
    	Person(const char *personname = "", int personalter = 0);
    	Person(const Person &);
    	~Person();
    	Person &operator=(const Person &);
    };
    
    Person::Person(const char *personname, int personalter)
    	{
    		pName = new char[strlen(personname)+1];
    		strcpy (pName, personname);
    		age = personalter;
    	}
    
    Person::Person(const Person &P)
    	{
    		pName = new char[strlen(P.pName)+1];
    		strcpy(pName, P.pName);
    		age = P.age;
    	}
    
    Person::~Person()
    	{
    		delete [] pName;
    	}
    
    Person &Person::operator=(const Person &P)
    	{
    		if(this != &P)
    		{
    			delete [] pName;
    			pName = new char[strlen(P.pName)+1];
    			strcpy(pName, P.pName);
    		}
    		return *this;
    	}
    
    void Person::setName(const char *personname)
    	{
    		assert(strlen(personname)<20);
    		strcpy(pName, personname);
    	}
    
    void Person::setAge(int personalter)
    	{
    		age = personalter;
    	}
    const char *Person::getName() const
    	{
    		return pName;
    	}
    
    int Person::getAge() const
    	{
    		return age;	
    	}
    
    	ostream &operator<<(ostream &os, const Person &Ausgabe)
    	{
    		return os << Ausgabe.getName() << " " << Ausgabe.getAge() << "\n";
    	}
    
    	istream &operator>>(istream &is, Person &Eingabe)
    	{
    		char name[20];
    		int age;
    		is.width(20);
    		is >> name >> age;
    		Eingabe.setName(name);
    		Eingabe.setAge(age);
    		return is;
    	}
    
    #endif // PER4_HPP
    


  • Hallo,
    ich denke mal, da liegt der Hund begraben:

    // nicht sinnvoll, aber muss moeglich sein 
     son = son; 
     cout << "son = " << son;
    

    da ja hier zunächst der Zuweisungs operator aufgerufen wird:

    Person &Person::operator=(const Person &P)
        {
            if(this != &P)
            {
                delete [] pName;
                pName = new char[strlen(P.pName)+1];
                strcpy(pName, P.pName);
            }
            return *this;
        }
    

    Was passiert? Nun, eine Instanz des Objektes Person bekommt im assignment operator die referenz auf sich selbst. Nun gibt die Instanz des Objektes den zuvor allokierten Speicher frei, und dann will sie auf Basis der ihr übergebenen Referenz neuen allokieren. So, und das anhand der übergebenen Referenz auf sich selbst! Geht so nicht. Referenzen sind, ob const oder nicht, im Prinzip Zeiger.

    Also, kommentiere mal die Zuweisung "son = son;" aus. Dann sollte alles gehen. Solltest Du allerdings so ein Konstrukt benötigen, dann mache aus

    Person &Person::operator=(const Person &P)
    
    Person &Person::operator=(Person P)
    

    Auch dann sollte es gehen.

    Gruss, Gio



  • Gio schrieb:

    ich denke mal, da liegt der Hund begraben:

    Nein, der Zuweisungsoperator hat doch eine explizite Prüfung auf Selbstzuweisung.
    Das ist nicht besonders schön, sollte aber funktionieren.

    Das Problem ist setName. Diese Methode geht einfach davon aus, dass genügend Speicher vorhanden ist, um den Namen hineinzukopieren. Das ist aber nicht immer der Fall.



  • Danke Leute jetzt geht es! Und zwar hat gestimmt was MFK geschrieben hat. Ich hatte vergessen in der Fkt. setName den Speicher nochmal zu überprüfen. Das hab ich jetzt gemacht und schon läuft es wie ich es will. Danke nochmal ihr seid super!!!



  • Autsch, da habe ich ja wirklich nicht richtig geschaut (und sogar den Code kopiert) (Der Smiley mit den roten Bäckchen ist leider nicht dabei 🙂 ).
    Habe glatt übersehen, dass der assignemt operator den Parameter auf sich selbst prüft.

    Soll nicht wieder vorkommen.

    Gruss, Gio


Anmelden zum Antworten