delete [] wskaźnik

delete [] wskaźnik
WI
  • Rejestracja:prawie 5 lat
  • Ostatnio:prawie 5 lat
  • Postów:2
0

Kiedy destruktor wchodzi do gry to dostaje błąd. Chce opróżnić w moim przypadku wsk. Nie potrafię zrozumieć, czy źle staram się usunąć ten wsk, a może błąd leży gdzieś indziej?
Mój program ma za zadanie dodać do siebie poprzez operator + dwa punktnD, które mają w sobie wymiar i zależną od niego dynamiczną tablicę.

Kopiuj
#include <iostream>
using namespace std;

class punktnD {
	int wymiar;
	int* wsk;
public :
	static int liczbaObiektow;
public:	
	punktnD(int n=2) :wymiar(n), wsk(new int[wymiar]) { 
		liczbaObiektow++; 
		cout << "konstruktor domyslny" << endl;
		cout << "wsk - " << *wsk << endl;
	}
	punktnD(const punktnD & pkt):wymiar(pkt.wymiar), wsk(new int[wymiar]) {
		int* tmp1 = pkt.wsk;
		int* tmp2 = wsk;

		for (int i = 0; i < wymiar; i++) {
			tmp2[i] = tmp1[i];
		}	
		cout << "konstruktor kopiujacy" << endl;
		liczbaObiektow++;
	}
	~punktnD() {
		liczbaObiektow--;
		delete [] wsk;
	}

	friend punktnD operator + (const punktnD& pkt1, const punktnD& pkt2) {
		punktnD pkt;
		if (pkt1.wymiar < pkt2.wymiar)
			pkt.wymiar = pkt2.wymiar;
		else pkt.wymiar = pkt1.wymiar;

		int* tmp1 = pkt1.wsk;
		int* tmp2 = pkt2.wsk;
		int* tmp3 = pkt.wsk;

		for (int i = 0; i < pkt.wymiar; i++) {
			tmp3[i] = tmp1[i] + tmp2[i];
		}

		return pkt;
	}
	
	friend istream& operator >> (istream& kl, punktnD& pkt) {
		for (int i = 0; i < pkt.wymiar; i++) {
			cout << "podaj " << i << " element" << endl;
			cin >> pkt.wsk[i];
		}
		return kl;
	}

	friend ostream& operator << (ostream& kl, punktnD& pkt)
	{
		for (int i = 0; i < pkt.wymiar; i++) {
			cout << "element " << i << " :" << pkt.wsk[i]<< endl;
		}
		return kl;
	}
};

int punktnD::liczbaObiektow = 0;
pylaochos
Co to znaczy, że " destruktor wchodzi do gry "?
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:około 3 godziny
0

Bo prawdopodobnie mażesz po pamięci. W operator + przydzielasz tablicę na 2 elementy;

Kopiuj
friend punktnD operator + (const punktnD& pkt1, const punktnD& pkt2)
    {
        punktnD pkt(pkt1.wymiar>pkt2.wymiar?pkt1.wymiar:pkt2.wymiar);
        for(int i=0;i<pkt.wymiar;++i)
        {
            pkt.wsk[i]=(i<pkt1.wymiar?pkt1.wsk[i]:0)+(i<pkt2.wymiar?pkt2.wsk[i]:0);
        }
        return pkt;
    }

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 1x, ostatnio: _13th_Dragon
WI
No właśnie nawet nie próbując dodać tych liczb, gdy po prostu jawnie sobie wywołam destruktor pkt1.~punktnD() (albo on sam ruszy do roboty) to program się wysypuje.
lion137
  • Rejestracja:około 8 lat
  • Ostatnio:4 minuty
  • Postów:4930
0

Jaki Masz błąd, bo lekko zmieniony kod (komunikat w destruktorze), kompilluje się i wykonuje bez błędów (g++-9, Ubuntu):

Kopiuj
#include <iostream>
using namespace std;

class punktnD {
    int wymiar;
    int* wsk;
public :
    static int liczbaObiektow;
public: 
    punktnD(int n=2) :wymiar(n), wsk(new int[wymiar]) { 
        liczbaObiektow++; 
        cout << "konstruktor domyslny" << endl;
        cout << "wsk - " << *wsk << endl;
    }
    punktnD(const punktnD & pkt):wymiar(pkt.wymiar), wsk(new int[wymiar]) {
        int* tmp1 = pkt.wsk;
        int* tmp2 = wsk;

        for (int i = 0; i < wymiar; i++) {
            tmp2[i] = tmp1[i];
        }   
        cout << "konstruktor kopiujacy" << endl;
        liczbaObiektow++;
    }
    ~punktnD() {
        std::cout <<" destr\n";
        liczbaObiektow--;
        delete [] wsk;
    }

    friend punktnD operator + (const punktnD& pkt1, const punktnD& pkt2) {
        punktnD pkt;
        if (pkt1.wymiar < pkt2.wymiar)
            pkt.wymiar = pkt2.wymiar;
        else pkt.wymiar = pkt1.wymiar;

        int* tmp1 = pkt1.wsk;
        int* tmp2 = pkt2.wsk;
        int* tmp3 = pkt.wsk;

        for (int i = 0; i < pkt.wymiar; i++) {
            tmp3[i] = tmp1[i] + tmp2[i];
        }

        return pkt;
    }

    friend istream& operator >> (istream& kl, punktnD& pkt) {
        for (int i = 0; i < pkt.wymiar; i++) {
            cout << "podaj " << i << " element" << endl;
            cin >> pkt.wsk[i];
        }
        return kl;
    }

    friend ostream& operator << (ostream& kl, punktnD& pkt)
    {
        for (int i = 0; i < pkt.wymiar; i++) {
            cout << "element " << i << " :" << pkt.wsk[i]<< endl;
        }
        return kl;
    }
};

int punktnD::liczbaObiektow = 0;

void test() {
     punktnD p{3};
}

int main() {
   test();
}

WI
.exe has triggered a breakpoint.
lion137
jaki kod powoduje ten błąd.
WI
delete [] wsk; z destruktora
WI
no kod jest taki jak wysłałem, zrobiłem screena jak to wygląda może to pomoże https://imgur.com/Tesv2FQ
lion137
  • Rejestracja:około 8 lat
  • Ostatnio:4 minuty
  • Postów:4930
1

g++, by Cię poinformował czytelniej: double free detected ; nie Wywołuj destruktora, on się sam uruchamia, jak obiekt wychodzi ze "scope", czyli u Ciebie dwa razy, a to jest no, no ;)


edytowany 1x, ostatnio: lion137
kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:Szczecin
2

Dodatkowa lektura:


WI
dzięki, przeczytam z pewnością
TomaszLiMoon
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 22 godziny
  • Postów:530
1
  1. Zmień tablicę na vector
  2. Zastosuj CRTP jako mechanizm zliczania istniejących obiektów. Możesz zlikwidować własny konstruktor kopiujący i destruktor. Wtedy kompilator będzie mógł utworzyć niejawnie konstruktor i operator przenoszący. Co za tym idzie w operatorze dodawania zwracany obiekt będzie mógł być przeniesiony.
Kopiuj
#include <iostream>
#include <vector>

using namespace std;

template <typename T>
struct Counter
{
    Counter(){ ++counter; }
    Counter( const Counter& ){ ++counter; }
    inline static int counter {0};

protected:
    ~Counter() { --counter; }
};

class Point : public Counter<Point>
{

    vector<int> component;

public:

    Point( int n=2 ){component.resize(n,n);}

    friend Point operator+( const Point& point1, const Point& point2 )
    {
        Point point { ((point1.component.size()>point2.component.size()) ? point1 : point2) };

        size_t index {0};
        for( const auto& value : ( (point1.component.size()<point2.component.size()) ? point1.component : point2.component ) )
        {
            point.component[index++] += value;
        }

        return point;
    }

    friend ostream& operator<<( ostream& out , const Point& point )
    {
        for( const auto& element : point.component )
        {
            out << element << " ";
        }
        return out;
    }


};

int main()
{
    Point p1 {10} , p2 {20};

    auto p = p1 + p2;

    cout << p1 << endl ;
    cout << p2 << endl ;
    cout << p << endl ;

    cout << Point::counter << endl;

    return 0;
}
edytowany 1x, ostatnio: TomaszLiMoon
kq
Dlaczego tam jest virtual? Jak dla mnie nie ma sensu na siłę wymuszać dynamicznego polimorfizmu.
TomaszLiMoon
Dodawanie virtual przed destruktorem, to taki sam nawyk jak porządna porcja kawy po przebudzeniu :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.