-1

So I have a class Vector and when I'm calling in main for example the destructor of an object I get an exception. The line of code from the exception file is "free_dbg(block, _UNKNOWN_BLOCK)"; Note that if I do only the reading of the vectors or only the destructor call, I won't get the exception. When I do both together, this is when the problem appears. Here is the code:

    #include "pch.h"
#include <iostream>
#include <fstream>
using namespace std;

class Vector
{
public:
    Vector();
    ~Vector();
    Vector(const Vector& vec);
    void insert_element(int value, int position);
    void delete_element(int position);
    void set_nr_elem(int nr) { nr_elem = nr; }
    int get_nr_elem() const { return nr_elem; }
    int get_element(int position) const { return arr[position]; }
    friend istream& operator>>(istream& input, Vector &vec);
    friend ostream& operator<<(ostream& output, const Vector &vec);
    Vector operator=(const Vector& vec);
    void free_memory() { delete[] arr; }
private:
    int *arr;
    int nr_elem;
};

Vector::Vector()
{
    arr = NULL;
    nr_elem = 0;
}

Vector::~Vector()
{
    delete[]arr;
    nr_elem = 0;
}

Vector::Vector(const Vector& vec)
{
    arr = new int[vec.nr_elem];
    nr_elem = vec.nr_elem;
    for (int i = 0; i < nr_elem; i++)
        arr[i] = vec.arr[i];
}

void Vector::insert_element(int value, int position)
{
    if (position < 0 || position > nr_elem)
    {
        cout << "Invalid position";
        return;
    }
    arr = (int*)realloc(arr, (nr_elem + 1) * sizeof(int));
    for (int i = nr_elem; i >= position + 1; i--)
        arr[i] = arr[i - 1];
    arr[position] = value;
    nr_elem++;
}

void Vector::delete_element(int position)
{
    if (position < 0 || position >= nr_elem)
    {
        cout << "Invalid position";
        return;
    }
    for (int i = position; i < nr_elem; i++)
        arr[i] = arr[i + 1];
    delete &arr[nr_elem];
    nr_elem--;
}

istream& operator>>(istream& input, Vector &vec)
{
    int nr;
    input >> nr;
    for (int i = 0; i < nr; i++)
    {
        int x;
        input >> x;
        vec.insert_element(x, vec.get_nr_elem());
    }
    return input;
}

ostream& operator<<(ostream& output, const Vector &vec)
{
    if (vec.get_nr_elem())
    {
        output << "Number of elements: " << vec.get_nr_elem() << "\n";
        output << "The elements: ";
        for (int i = 0; i < vec.get_nr_elem(); i++)
            output << vec.get_element(i) << " ";
        output << "\n";
    }
    else
    {
        output << "The vector has no elements";
    }
    return output;
}

Vector Vector::operator=(const Vector& vec)
{
    if (this == &vec)
        return *this;
    delete[] arr;
    arr = new int[vec.nr_elem];
    for (int i = 0; i < vec.nr_elem; i++)
        arr[i] = vec.arr[i];
    nr_elem = vec.nr_elem;
    return *this;
}

class Natural_Big_Number 
{
public:
    void set_sign(char c) { sign = c; }
    char get_sign() const { return sign; }
    friend istream& operator>>(istream& input, Natural_Big_Number &number);
    friend ostream& operator<<(ostream& output, const Natural_Big_Number &number);
    friend Natural_Big_Number operator+(const Natural_Big_Number& number1, const Natural_Big_Number& number2);
    friend Natural_Big_Number operator-(const Natural_Big_Number& number1, const Natural_Big_Number& number2);
    friend Natural_Big_Number& operator*(const Natural_Big_Number& number1, const Natural_Big_Number& number2);
    friend Natural_Big_Number& operator/(const Natural_Big_Number& number1, const Natural_Big_Number& number2);
    Natural_Big_Number operator=(const Natural_Big_Number& number);

private:
    Vector vec;
    char sign;
};

istream& operator>>(istream& input, Natural_Big_Number &number)
{
    int x;
    input >> x;
    char c;
    input.get();
    c = input.get();
    if (c == '-')
        number.set_sign('-');
    else
    {
        number.set_sign('+');
        int digit = (int)c - 48;
        number.vec.insert_element(digit, number.vec.get_nr_elem());
    }
    while ((c = input.get()) >= '0' && c <= '9')
    {
        int digit = (int)c - 48;
        number.vec.insert_element(digit, number.vec.get_nr_elem());
    }
    return input;
}

ostream& operator<<(ostream& output, const Natural_Big_Number &number)
{
    cout << "Number of digits: " << number.vec.get_nr_elem() << '\n';
    cout << "The number: ";
    if (number.get_sign() == '-')
        cout << number.get_sign();
    for (int i = 0; i < number.vec.get_nr_elem(); i++)
        cout << number.vec.get_element(i);
    cout << endl;
    return output;
}

Natural_Big_Number operator+(const Natural_Big_Number& number1, const Natural_Big_Number& number2)
{
    Natural_Big_Number result;
    int carry = 0;
    int it_digits1 = number1.vec.get_nr_elem() - 1;
    int it_digits2 = number2.vec.get_nr_elem() - 1;
    if (number1.get_sign() == number2.get_sign())
    {
        result.set_sign(number1.get_sign());
        while (it_digits1 >= 0 && it_digits2 >= 0)
        {
            int aux = number1.vec.get_element(it_digits1) + number2.vec.get_element(it_digits2) + carry;
            int value = aux % 10;
            result.vec.insert_element(value, 0);
            carry = aux / 10;
            it_digits1--;
            it_digits2--;
        }
        for (int i = 0; i <= it_digits1; i++)
        {
            int aux = number1.vec.get_element(it_digits1) + carry;
            int value = aux % 10;
            carry = aux / 10;
            result.vec.insert_element(value, 0);
        }
        for (int i = 0; i <= it_digits2; i++)
        {
            int aux = number2.vec.get_element(it_digits2) + carry;
            int value = aux % 10;
            carry = aux / 10;
            result.vec.insert_element(value, 0);
        }
    }
    /*else if (number1.get_sign() == '-' && number2.get_sign() == '+')
    {
        result = number1;
        result.set_sign('+');
        result = number2 + result;
    }*/
    cout << result;
    return result;
}

Natural_Big_Number operator-(const Natural_Big_Number& number1, const Natural_Big_Number& number2)
{
    Natural_Big_Number result;
    int carry = 0;
    int it_digits1 = number1.vec.get_nr_elem() - 1;
    int it_digits2 = number2.vec.get_nr_elem() - 1;
    while (it_digits1 >= 0 && it_digits2 >= 0)
    {
        int aux = number1.vec.get_element(it_digits1) - number2.vec.get_element(it_digits2) + carry;
        int value = aux % 10;
        result.vec.insert_element(value, 0);
        carry = aux / 10;
        it_digits1--;
        it_digits2--;
    }
    for (int i = 0; i <= it_digits1; i++)
    {
        int aux = number1.vec.get_element(it_digits1) + carry;
        int value = aux % 10;
        carry = aux / 10;
        result.vec.insert_element(value, 0);
    }
    for (int i = 0; i <= it_digits2; i++)
    {
        int aux = number2.vec.get_element(it_digits2) + carry;
        int value = aux % 10;
        carry = aux / 10;
        result.vec.insert_element(value, 0);
    }
    cout << result;
    return result;
}

Natural_Big_Number Natural_Big_Number::operator=(const Natural_Big_Number& number)
{
    if (this == &number)
        return *this;
    vec.free_memory();
    set_sign(number.get_sign());
    vec = number.vec;
    return *this;
}

int main()
{
    ifstream f("date.in");
    Natural_Big_Number number1, number2;
    f >> number1 >> number2;
    number1 = number2;
    cout << number1;

    return 0;
}
  • 1
    Usage of `placement new` is pretty close to being the *only* time you'd ever want to explicitly call a destructor. – Jesper Juhl Apr 03 '19 at 16:32

1 Answers1

4

That's because you shouldn't do that.

The destructor is called for you when vec1 goes out of scope.

Your program attempts to destroy vec1 twice, which causes mayhem.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Ohh, what I wanted to do is use the destructor to free the memory in a function instead of writing another function, I did not think about that. Thanks a lot – Alin Catalin Preda Apr 03 '19 at 16:11
  • 2
    I don't follow. Why do you need to write another function? The destructor looks right; just don't call it manually. – Lightness Races in Orbit Apr 03 '19 at 16:12
  • Because in the operator= from Natural_Big_Number I have to free the memory from the vector member before assigning to another. – Alin Catalin Preda Apr 03 '19 at 16:23
  • 1
    @AlinCatalinPreda *Because in the operator= from Natural_Big_Number* -- What is "Natural_Big_Number"? And none of what you say is required by explicitly calling the destructor. That's just you assuming you need to do this erroneous step. – PaulMcKenzie Apr 03 '19 at 16:47
  • That's what my teachers told us to do, to always free the memory even if it's done automatically when the scope of the variable is ending, – Alin Catalin Preda Apr 03 '19 at 17:04
  • Then you misinterpreted what your teacher is telling you. The teacher didn't mean to actually call the destructor explicitly. – PaulMcKenzie Apr 03 '19 at 17:06
  • https://www.heypasteit.com/clip/0ISBZ1 here is the Natural_Big_Number class – Alin Catalin Preda Apr 03 '19 at 17:07
  • Yes that was just a bad idea of mine, they told us just to free it but when I try to free it with a function because i cant access the array dirrectly is still the same problem – Alin Catalin Preda Apr 03 '19 at 17:08
  • Please do not post links to random sites. Post the code here (in your original message and explain what the issue is) – PaulMcKenzie Apr 03 '19 at 17:10
  • I can't paste so much code – Alin Catalin Preda Apr 03 '19 at 17:14
  • I edited it in the post with the whole code – Alin Catalin Preda Apr 03 '19 at 17:15
  • @AlinCatalinPreda I don't know what your teachers are really telling you, but `vec` in your `Natural_Big_Number` class will be automatically destroyed, since `Vector` handles the memory management already. If C++ didn't work this way, imagine that crazy code that had to be written by us programmers just to clean up the memory. Also, `Vector Vector::operator=(const Vector& vec)` is not correct. It should be `Vector& Vector::operator=(const Vector& vec)` – PaulMcKenzie Apr 03 '19 at 17:17
  • Can you explain why it should be with &? It works just fine without it – Alin Catalin Preda Apr 03 '19 at 17:29
  • https://imgur.com/a/Ljj4O62 here is a picture with the overload of some operators from my course – Alin Catalin Preda Apr 03 '19 at 17:33
  • @Alin: Paul's right (and [here's why](https://stackoverflow.com/q/21485366/560648)). But it does appear that this comes from your teacher :( Your version "works just fine" in a sense, but has unconventional/surprising op definitions that may/will result in unconventional/surprising results... – Lightness Races in Orbit Apr 03 '19 at 17:41