-2

Okay so I have this homework problem with c++ and deleting a dynamic array. When I run the program, it shows me the following: http://prntscr.com/p015e9 I guess the problem is something with deleting the pointers because i traced it to these lines:

delete[] _elementi1; _elementi1 = nullptr;
delete[] _elementi2; _elementi2 = nullptr;

This is my class and the error occurs when I call the "Dodaj" function

template<class T1, class T2 = int>
class FITKolekcija {

    T1 * _elementi1;
    T2 * _elementi2;
    int _trenutno;

    public:
    FITKolekcija() {
        _elementi1 = nullptr; // Elements 1 pointer
        _elementi2 = nullptr; // Elements 2 pointer
        _trenutno = 0; // This is the _current variable and is used as an iterator
    }
    ~FITKolekcija() {
        try {
            delete[] _elementi1; _elementi1 = nullptr;
            delete[] _elementi2; _elementi2 = nullptr;
        }
        catch (exception& e) {

            cout << e.what() << endl;
        }
    }
    T1 * GetT1() { return _elementi1; }
    T2 * GetT2() { return _elementi2; }
    int GetTrenutno() { return _trenutno; }

    friend ostream& operator<< (ostream &COUT, FITKolekcija &obj) {
        for (size_t i = 0; i < obj._trenutno; i++)
            COUT << obj._elementi1[i] << " " << obj._elementi2[i] << endl;
        return COUT;
    }

    void Dodaj(T1 clan1, T2 clan2) {

        T1 *temp1 = new T1[_trenutno + 1];
        T2 *temp2 = new T2[_trenutno + 1];

        for (size_t i = 0; i < _trenutno; i++) {

            temp1[i] = _elementi1[i];
            temp2[i] = _elementi2[i];
        }

        delete[] _elementi1; _elementi1 = nullptr; // Here lies the runtime error
        delete[] _elementi2; _elementi2 = nullptr;

        temp1[_trenutno] = clan1;
        temp2[_trenutno] = clan2;

        _elementi1 = temp1;
        _elementi2 = temp2;

        _trenutno++;

    //
    }
}

With the following code, I get to execude "Dodaj" 7 times before the runtime error occurs with the following:

int main() {
int v6 = 6, v13 = 13, v32 = 32, v63 = 63, v98 = 98, v109 = 109, v196 = 196;

FITKolekcija<int, int> numbers;

cout << "1" << endl;
numbers.Dodaj(v196, v6);
cout << "2" << endl;
numbers.Dodaj(v13, v32);
cout << "3" << endl;
numbers.Dodaj(v98, v196);
cout << "4" << endl;
numbers.Dodaj(v63, v13);
cout << "5" << endl;
numbers.Dodaj(v98, v196);
cout << "6" << endl;
numbers.Dodaj(v196, v6);
cout << "7" << endl;

return 0;
}
JFKay
  • 39
  • 1
  • 7
  • 2
    Why are you using raw arrays and pointers at all? There are [containers](https://en.cppreference.com/w/cpp/container) and [dynamic memory management](https://en.cppreference.com/w/cpp/memory) available with standard c++. – πάντα ῥεῖ Aug 31 '19 at 14:58
  • 3
    In `Dodaj`, you create an array and store it's pointer in `temp1`, then you assign member pointer `_elementi1 ` to point to that same array, and then you immediately delete the array you created (which makes `_elementi1` a dangling pointer). – Yksisarvinen Aug 31 '19 at 15:00
  • @πάνταῥεῖ , as I said, its a homework problem and we must correct the given program to work. As such we must work with raw pointers. – JFKay Aug 31 '19 at 15:07
  • 1
    @JFKay Your teacher does teaching c++ the wrong way IMHO. – πάντα ῥεῖ Aug 31 '19 at 15:08
  • @Yksisarvinen I don't quite understand. Don't I have to delete the space at the pointer location and allocate the new to it so I don't get mem leak. Could you provide a snippet on how you would do it? I would be most thankful. Also I updated the code – JFKay Aug 31 '19 at 15:09
  • @πάνταῥεῖ I agree.. – JFKay Aug 31 '19 at 15:09
  • Reminder: `delete` is for single objects; `delete[]` is for arrays of objects. – Thomas Matthews Aug 31 '19 at 17:57

1 Answers1

2

First, let me recommend you a good C++ book. StackOverflow is not the best place for learning the basics.

Pointer is a box. In this box, you can put a single piece of paper with a single address on it. When you have a pointer, it's normally not associated with any existing object (no address stored in the box):

int my_p;

my_p
--------
| NULL |
--------

When you use new, you can get a pointer to some real object somewhere (you build a real building somewhere and you write down it's address).

my_p = new int[5];

my_p
----------
| 0x2358 |
----------

 0x2358   0x2359   0x2360   0x2361   0x2362
-------- -------- -------- -------- -------- 
|   0  | |   0  | |   0  | |   0  | |   0  | 
-------- -------- -------- -------- -------- 

You can edit the object pointed to by pointer as you please(you know the address, you can go to the building and paint walls there):

my_p[2] = 13;

my_p
----------
| 0x2358 |
----------

 0x2358   0x2359   0x2360   0x2361   0x2362
-------- -------- -------- -------- -------- 
|   0  | |   0  | |  13  | |   0  | |   0  | 
-------- -------- -------- -------- -------- 

Now, when you copy a pointer, you only copy a pointer, not the object it points to(You get a new box and place the same address in this box):

int* my_p2 = my_p;

my_p       my_p2
---------- ----------
| 0x2358 | | 0x2358 | 
---------- ----------

 0x2358   0x2359   0x2360   0x2361   0x2362
-------- -------- -------- -------- -------- 
|   0  | |   0  | |  13  | |   0  | |   0  | 
-------- -------- -------- -------- -------- 

my_p2 has exactly the same properties as my_p and it points to exactly the same object as my_p(having either box, you can go to house and place a carpet there):

my_p2[3] = 26;

my_p
----------
| 0x2358 |
----------

 0x2358   0x2359   0x2360   0x2361   0x2362
-------- -------- -------- -------- -------- 
|   0  | |   0  | |  13  | |  26  | |   0  | 
-------- -------- -------- -------- -------- 
std::cout << my_p[3]; // prints 26, even though you used my_p2

When you delete an object, it's marked as free for use of compiler again. (you take the address and destroy building at that address). Note that you have no guarantee what is in that memory - it can be absolutely anything from now on.

delete[] my_p;

my_p       my_p2
---------- ----------
| 0x2358 | | 0x2358 | 
---------- ----------

 0x2358   0x2359   0x2360   0x2361   0x2362
-------- -------- -------- -------- -------- 
| FREE | | FREE | | FREE | | FREE | | FREE | 
-------- -------- -------- -------- -------- 

But the pointers itself didn't change! They are still pointing to the same location in the memory (you destroyed the house, but boxes are still safe somewhere else and noone chenged anything in these boxes) .
This is what we call a dangling pointer. If you now try to use object pointed to by such pointer, you get Undefined Behaviour (you brought paint and brushes and went to the given address, but there's no house to paint, or worse - someone else has already built their house there!)

std::cout << my_p2[2]; //can format your C drive if it wishes to do so
Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52