-5

I'm doing program for people register and i have problem with overloading operator =.

I have class CRegister, struct Person and Place.

struct Places{
    char date[11];
    char * street;
    char * city;

Places & operator = (const Places & other){
        delete [] street;
        delete [] city;

        strncpy (date, other.date, 11);

        int len;
        len = strlen(other.street);
        this->street = new char[len];
        strncpy ( this->street, other.street, len );

        len = strlen(other.city);
        this->city = new char[len];
        strncpy ( this->city, other.city, len );

        return *this;
    }
}


struct Person{
    char id[12];
    char * name;
    char * surname;
    Places ** oldPlaces;

    int placesCount;
    int placesSize;
};

Person & Person::operator =(const Person& other){
    for (int i = 0; i < this->placesSize; i++){
         delete this->oldPlaces[i];
    }
    delete [] this->oldPlaces;
    delete [] name;
    delete [] surname;


    placesCount = other.placesCount;
    placesSize = other.placesSize;

    oldPlaces = new Places*[other.placesSize];

    strncpy (id, other.id, 11);

        int len;

        len = strlen(other.name);
        this->name = new char[len];
        strncpy ( this->name, other.name, len );

        len = strlen(other.surname);
        this->surname = new char[len];
        strncpy ( this->surname, other.surname, len );

    for (int i = 0; i < placesCount; i++){
        oldPlaces[i] = other.oldPlaces[i];
    }

    return *this;
}



class CRegister     
 {
   private:
    Person **persons;
    int personCount;
    int personSize;
 };

 CRegister& CRegister::operator =(const CRegister& other){
    for (int i = 0; i < this->personSize; i++){
        delete this->persons[i];
    }
    delete [] this->persons;

    personCount = other.personCount;
    personSize = other.personSize;

    persons = new Person*[other.personSize];

    for (int i = 0; i < personCount; i++){
        persons[i] = other.persons[i];
    }


    return *this; 
 }

However, the code has compiled but Netbeans shows me Run failed. Why?

3 Answers3

2
    len = strlen(other.city);
    this->city = new char[len];
    strncpy ( this->city, other.city, len );

This does not preserve the length of the string. How will later code know how long this->city is?

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
1

You are not following the Rule of Three. It could possibly be one reason if not the only reason.

On another note,

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
1

Since you're basically using C (wrapped in a class): you've made what is probably the most frequent error in C code. strlen returns the number of characters in the string, not counting the final '\0'. strcpy copies the final '\0', so one more character, If you use strncpy (as you do, which you shouldn't), then you will end up with a string which is not '\0' terminated. So with strcpy, you overrun the end of the buffer, and with strncpy, anyone trying to read the string will overrun the end of the buffer (since they will continue until a '\0').

The rule is to allocate one more character than strlen returns:

size_t len = strlen( other.name ) + 1;
name = new char[ len ];
strcpy( name, other.name );

(Although not standard C, many systems have a strdup function which does this. Using malloc, of course, so you would have to free with free, and not delete.)

Beyond that, I will repeat what I said before: your code will leave the object in an inconsistent state if any of the allocations failed. Always do everything which can fail before modifying anything in your class. The swap idiom is classical for operator=, but otherwise, you can use local pointers:

char* newName = NULL;
char* newSurname = NULL;
Places* newPlaces = NULL;

try {
    newName = strdup( other.name);
    newSurname = strdup( other.surname );
    newPlaces = deapCopyPlaces( other.places );
} catch ( ... ) {
    deepDelete( newPlaces );
    delete [] newName;
    delete [] newSurname;
}
//  And only now...
deepDelete( places );
delete [] name;
delete [] surname;
name = newName;
surname = newSurname;
places = newPlaces;

But the swap idiom is far preferrable, because it avoids having to duplicate the all of the error handling code.

James Kanze
  • 150,581
  • 18
  • 184
  • 329