T0nd0Tara
T0nd0Tara

Reputation: 122

Destructor crashes when working with pointers in Visual Studio

When I'm using a pointer to an instance to this class, for some reason it crashes when it comes to the destructor. It works when I'm not using pointers

The weirdest part is that it works in VC Code but not in Visual Studio.

Polynomial.h

class Polynomial {
private:

    int32_t* coeffs;
    uint32_t deg;

public:

    Polynomial(int32_t* setCoeffs, uint32_t setDeg) {
        deg = setDeg;
        while (setCoeffs[deg] == 0 && deg > 0) deg--;

        coeffs = new int32_t[deg + 1]();
        for (uint32_t i = 0; i <= deg; i++) {
            coeffs[i] = setCoeffs[i];
        }
    }

    ~Polynomial () {
        delete[] coeffs;
    }

    std::string str() {
        std::string out = "";
        for (uint32_t i = deg; i > 0; i--) {
            if (coeffs[i] == 0) continue;
            if (coeffs[i] > 0 && i != deg) out += "+";

            if (coeffs[i] != 1)
                out += std::to_string(coeffs[i]);

            if (i == 1) out += "x";
            else if (i > 1) out += "x^" + std::to_string(i);
        }
        if (coeffs[0] != 0) {
            if (coeffs[0] > 0) out += "+";
            out += std::to_string(coeffs[0]);
        }
        return out;
    }




    friend std::ostream& operator<<(std::ostream& out, Polynomial p) {
        out << p.str();
        return out;
    }
};

main.cpp

#include <iostream>
#include "Polynomial.h"

int main(){
    int32_t* coeffs = new int32_t[3]();
    coeffs[0] = 5;
    coeffs[1] = 4;
    coeffs[2] = 3;
    Polynomial* p = new Polynomial(coeffs, 2);
    std::cout << (*p);
    delete p;
    return 0;
}

I'm guessing it's something to do with the Visual Studio properties but I don't know what to change.

Upvotes: 1

Views: 119

Answers (1)

Adrian Mole
Adrian Mole

Reputation: 51874

Your overload of the << operator takes its argument by value; so, in the line, std::cout << (*p); a copy of *p is made and, when the output is done, that copy is destroyed. However, as pointed out in the comments, you haven't implemented a proper copy constructor, so the compiler provides a default, which simply copies the data members' values (including the int32_t* coeffs pointer member).

So, when the output operation is done, and the copy is destroyed, the memory pointed-to by coeffs is deleted; then, when you come to delete the original, you are trying to delete that same memory a second time – hence the crash.

To fix the issue either: (a) implement proper copy and assignment constructors, which make real copies of the coeffs data; or (b) give the argument to your << operator by reference, as follows:

friend std::ostream& operator<<(std::ostream& out, Polynomial& p) { // Pass "p" BY REFERENCE
    out << p.str();
    return out;
}

Of course, making the '(b)' change doesn't (shouldn't) mean that you can't also implement '(a)'. You should really do both; here's a likely implementation of the copy constuctor:

Polynomial(const Polynomial& rhs) {
    deg = rhs.deg;
    coeffs = new int32_t[deg + 1];
    for (uint32_t i = 0; i <= deg; i++) {
        coeffs[i] = rhs.coeffs[i];
    }
}

Upvotes: 2

Related Questions