Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Problem z dynamicznym alokowaniem pamięci w metodzie klasy i jej zwalnianiem - przeciążanie operatora dodawania

Ostatnio zmodyfikowano 2017-08-17 20:16
Autor Wiadomość
Alchemik
Temat założony przez niniejszego użytkownika
Problem z dynamicznym alokowaniem pamięci w metodzie klasy i jej zwalnianiem - przeciążanie operatora dodawania
» 2017-08-17 12:44:33
Cześć,

W mojej klasie chciałem przeciążyć operator dodawania, aby móc dodać dwa ciągi znajdujące się w dwóch obiektach. Każdy z ciągów jest zapisany w dynamicznej tablicy znaków. Przy jednym dodawaniu nic się nie dzieje, jednak później pojawia się błąd:

This application has requested the Runtime to terminate it in unusual way. Please contact the application's support team for more information,

lub program przestaje dziełać

Czy ktoś spotkał się z podobnym problemem, albo wie jaka jest przyczyna?

Link do programu po kompilacji: http://ifotos.pl/zobacz​/Beztytulu_qhraawr.png

Kod:


1) Deklaracja klasy:
C/C++
#ifndef COW_HPP
#define COW_HPP
#include <iostream>
class cow
{
    static int number_of_objects;
    char name[ 20 ];
    char * hobby;
    double weight;
    int number;
    ///methods
    void show_number_of_object( char * s );
public:
    cow();
    cow( const char * nm, const char * ho, double wt );
    cow( const cow & t );
    ~cow();
    cow operator =( const cow & t );
    cow & operator +( const cow & t );
    void ShowCow(); ///showing object's data
    friend std::ostream & operator <<( std::ostream & os, const cow & t );
   
};
#endif // COW_HPP

Przeciazanie metody dodawania:
C/C++
cow & cow::operator +( const cow & t )
{
    int length = strlen( t.hobby ) + strlen( hobby );
    char * temp = new char[ length ];
    strcpy( temp, hobby );
    strcat( temp, " " );
    strcat( temp, t.hobby );
    delete[] hobby; ///wyczyszczenie miejsca,  na ktore wskazuje hobby
    hobby = new char[ length + 1 ]; ///zadeklarowanie nowego miejsca na hobby
    strcpy( hobby, temp );
    delete[] temp; ///wykasowanie tablicy temp, ktora slzy do tymczasowego przeniesienia iagow
    return * this;
}

Program:
C/C++
int main()
{
    cow Krowa1( "Krasula", "Ala ma", 250 );
    cow Krowa2( "Barbara", "kota", 150 );
    Krowa1.ShowCow();
    Krowa1 + Krowa2 + Krowa1;
    Krowa1.ShowCow();
    Krowa2.ShowCow();
    Krowa2 + Krowa1;
    Krowa2.ShowCow();
    Krowa2 + Krowa2;
    return 0;
}

Konstruktor i destruktor:
C/C++
cow::cow()
{
    number_of_objects++;
    const char * s = "Bez nazwy";
    hobby = new char[ strlen( s ) + 1 ];
    strcpy( hobby, s );
    strcpy( name, "Nazwa obiektu" );
    weight = 0.0;
    number = number_of_objects;
}
cow::cow( const char * nm, const char * ho, double wt )
{
    number_of_objects++;
    number = number_of_objects;
    weight = wt;
    hobby = new char[ strlen( ho + 1 ) ];
    strcpy( hobby, ho );
    strcpy( name, nm );
}

cow::~cow()
{
    number_of_objects--;
    delete[] hobby;
}
 
P-164052
Kinexity
» 2017-08-17 15:27:52
Przejdźmy po kolei:
1. Zmienna number_of_objects nie została zainicjalizowana.
2. Jak wywala błąd to wybierz opcję debugowania. Najprawdopodobniej masz VS, który automatycznie skojarzony program z rozwiązaniem i wskaże ci miejsce błędu.
3. Nikt ci nie wywróży rozwiązania z informacji, że program wymusił zakończenie działania w nadzwyczajny sposób, ponieważ to może być cokolwiek zaczynając od dzielenia przez zero a kończąc na złamaniu zasad dostępu.
4. Skoro to jest C++, a nie tylko C, to możesz przecież używać std::string, który ma wbudowane przeciążenie operatora + do łączenia ciągów znaków, co by wiele uprościło.
P-164056
Alchemik
Temat założony przez niniejszego użytkownika
» 2017-08-17 17:26:19
Przejdźmy po kolei:
1. Zmienna jest zainicjalizowana, wkleiłem tylko te fragmentu kodu, które dotyczą wysypywania się programu.
2. Program się kompiluje, nie chodzi o to, że się nie włącza - po prostu w trakcie wykonywania pojawia się błąd który jest na screenie. Debugowanie zatem nic nie daje.
3. Jeżeli ktoś chciałby pomóc, to wklejam poniżej cały kod programu, ale wątpię czy reszta kodu ma coś do mojego problemu.
4. Wiem, że istnieje biblioteka string, chciałem to zrobić na dynamicznym przydzielaniu pamięci jako ćwiczenie, ze stringiem łączenie dwóch ciągów znaków jest za łatwe.

Mam nadzieję, że ktoś próbował czegoś podobnego(tzn łączenie dwóch ciągów z tablic dynamicznych) i podpowie swoje rozwiązanie. Sam sporo próbowałem tutaj modyfikować, jednak program nadal się wysypuje. Dziękuje za wszystkie pomocne sugestie.

Cały kod:

Plik nagłówkowy:

C/C++
#ifndef COW_HPP
#define COW_HPP
#include <iostream>
class cow
{
    static int number_of_objects;
    char name[ 20 ];
    char * hobby;
    double weight;
    int number;
    ///methods
    void show_number_of_object( char * s );
public:
    cow();
    cow( const char * nm, const char * ho, double wt );
    cow( const cow & t );
    ~cow();
    cow operator =( const cow & t );
    cow & operator +( const cow & t );
    void ShowCow(); ///showing object's data
    friend std::ostream & operator <<( std::ostream & os, const cow & t );
   
};
#endif // COW_HPP

Metody:
C/C++
#include "cow.hpp"
#include <cstring>
#include <iostream>

int cow::number_of_objects = 0;

cow::cow()
{
    number_of_objects++;
    const char * s = "Bez nazwy";
    hobby = new char[ strlen( s ) + 1 ];
    strcpy( hobby, s );
    strcpy( name, "Nazwa obiektu" );
    weight = 0.0;
    number = number_of_objects;
}
cow::cow( const char * nm, const char * ho, double wt )
{
    number_of_objects++;
    number = number_of_objects;
    weight = wt;
    hobby = new char[ strlen( ho + 1 ) ];
    strcpy( hobby, ho );
    strcpy( name, nm );
}

cow::~cow()
{
    number_of_objects--;
    delete[] hobby;
}

void cow::show_number_of_object( char * s )
{
    std::cout << "Numer obiektu: \"" << s << "\" wynosi: " << number << std::endl;
}
void cow::ShowCow()
{
    show_number_of_object( name );
    std::cout << "Opis: " << hobby << std::endl;
    std::cout << "Waga: " << weight << std::endl;
}
cow cow::operator =( const cow & t )
{
    //std::cout << "Wywolano operator przypisania!\n";
    delete[] hobby;
    int length = strlen( t.hobby );
    hobby = new char[ length + 1 ];
    strcpy( hobby, t.hobby );
    strcpy( name, t.name );
    weight = t.weight;
    return * this;
   
}

cow::cow( const cow & t )
{
    //std::cout << "Wywolano konstruktor kopiujacy!\n";
    number_of_objects++;
    number = number_of_objects;
    int length = strlen( t.hobby );
    hobby = new char[ length + 1 ];
    strcpy( hobby, t.hobby );
    strcpy( name, t.name );
    weight = t.weight;
    //return *this;
}

cow & cow::operator +( const cow & t )
{
    int length = strlen( t.hobby ) + strlen( hobby );
    char * temp = new char[ length ];
    strcpy( temp, hobby );
    strcat( temp, " " );
    strcat( temp, t.hobby );
    delete[] hobby; ///wyczyszczenie miejsca,  na ktore wskazuje hobby
    hobby = new char[ length + 1 ]; ///zadeklarowanie nowego miejsca na hobby
    strcpy( hobby, temp );
    delete[] temp; ///wykasowanie tablicy temp, ktora slzy do tymczasowego przeniesienia iagow
    return * this;
}



std::ostream & operator <<( std::ostream & os, const cow & t )
{
    os << "Obiekt numer: " << cow::number_of_objects;
    return os;
}

Kod z funkcją main:
C/C++
#include <iostream>
#include "cow.hpp"
#include <cstring>


int main()
{
    cow Krowa1( "Krasula", "Ala ma", 250 );
    cow Krowa2( "Barbara", "kota", 150 );
    Krowa1.ShowCow();
    Krowa1 + Krowa2 + Krowa1;
    Krowa1.ShowCow();
    Krowa2.ShowCow();
    Krowa2 + Krowa1;
    Krowa2.ShowCow();
    Krowa2 + Krowa2;
    return 0;
}
P-164068
Luq
» 2017-08-17 17:30:45
C/C++
int length = strlen( t.hobby ) + strlen( hobby );
char * temp = new char[ length ];
strcpy( temp, hobby );
strcat( temp, " " );
strcat( temp, t.hobby );
W temp brakuje miejsca na spację i '\0'
P-164069
Kinexity
» 2017-08-17 19:26:28
Ale debugowanie wskazuje linię kodu, na której wystąpił błąd, oraz podaje szczegóły (w tym też zawartość pamięci przypisanej programu w momencie przerwania działania)- mniej więcej tak to wygląda:

 
P-164073
mateczek
» 2017-08-17 20:16:17
Oczywiście trzeba dodać do rozmiaru 2 jak zasugerował Luk. A ja bym jeszcze pokasował niepotrzebne operacje
C/C++
cow & cow::operator +( const cow & t )
{
    int length = strlen( t.hobby ) + strlen( hobby ) + 2; // jak słusznie zauważył Luk
    char * temp = new char[ length ];
    strcpy( temp, hobby );
    strcat( temp, " " );
    strcat( temp, t.hobby );
    delete[] hobby;
    hobby = temp; // po prostu, reszta jest zbędna :P
    //hobby = new char[ length + 1 ]; ///zadeklarowanie nowego miejsca na hobby
    //strcpy( hobby, temp );
    //delete[] temp; ///wykasowanie tablicy temp, ktora slzy do tymczasowego przeniesienia iagow
    return * this;
}
P-164075
« 1 »
  Strona 1 z 1