0

I'm working on a homework assignment. I'm trying to overload the "=" operator for an Array class I'm creating so that it will assign a newly created array with the same values as another array. This seems to work. The array is created and the data is copied over. I also check the location of the arrays first element and it is different than the original so I don't think it's trying to delete an array that's already deleted.

I've tried messing around with my destructor, but I honestly have no idea where this is coming from. If anyone has any debugging strategies that might help, I'd love to hear them as well.

Driver.cpp


    int main ()
    {
            //Initialize 
        int size = 0;
        char fill = '\0';

            //Get info about the array
        std::cout << "How long should the array be?" << std::endl;
        std::cin >> size;
        std::cout << "Choose fill character." << std::endl;
        std::cin >> fill;

            //Create array & Print array details
        Array* arr = new Array(size, fill);
        std::cout << "The array size is: " << arr->size() << std::endl;
        std::cout << "max size: " << arr->max_size() << std::endl;
        std::cout << "The contents of the array is: ";
        arr->printArr();
        std::cout << std::endl;

        //Create new array & set it's values equal to old array
        Array* arr2 = new Array();
        arr2 = arr;

        //= OVERLOAD TESTING
        std::cout << "The array size is: " << arr2->size() << std::endl;
        std::cout << "max size: " << arr2->max_size() << std::endl;
        std::cout << "The contents of the array is: ";
        arr2->printArr();

        //Deallocate memory 
        delete arr;
        arr = nullptr;
        delete arr2;
        arr2 = nullptr;

        //Checking for memory leaks 
        _CrtDumpMemoryLeaks();

        return 0;
    }

Array.cpp file

//Define MAX SIZE so that it can be easily changed.
#define MAX_SIZE_ 200

#include "Array.h"
#include <iostream>
#include <stdexcept>

Array::Array (void)
    :data_ (new char[MAX_SIZE_]), 
    cur_size_ (0), 
    max_size_ (MAX_SIZE_) 
{   }

//Overloaded Constructor 
//Assigns the initial size of the array and fills each element with the character stored in fill.
Array::Array (size_t length, char fill)
    : data_ (new char[length]), 
    cur_size_ (length), 
    max_size_ (length) 
{   
    //Fill each element with the character passed in to the function.
    for(int i = 0; i < length; i++)
    {
        this-> data_[i] = fill; 
    }

    std::cout << &this->data_ << std::endl;
} 

//Destructor
Array::~Array (void)
{
    delete[] this->data_;
    this->data_ = nullptr;
}

//Sets new array equal to rhs.
const Array & Array::operator = (const Array & rhs)
{
    //Set current and max size values to new array.
    this->max_size_ = rhs.max_size_;
    this->cur_size_ = rhs.cur_size_;

    //Copy data from rhs.data_ to new array's data_
    for(int i = 0; i < rhs.cur_size_; i++)
    {
        this->data_[i] = rhs.data_[i];
    }

    return *this;
}

//Print the contents of the array.
void Array::printArr(void)
{
    for (int i = 0; i < (this->cur_size_) ; i++)
    {
        std::cout << this->data_[i];
    }
}

Expected Results: The program displays information about the different arrays, then deletes them with no memory leaks.

Actual Results: The program displays all the correct data for both arrays and is able to delete the first array without a hitch, but runs into an exception when calling:

delete[] this->data_;

on the second array.

> Exception thrown at 0x5D13DB1B (ucrtbased.dll) in driver.exe: 0xC0000005: Access violation reading location 0xDDDDDDCD

Thanks for any help!
bonzi
  • 1
  • 1
  • Where is the copy constructor for `Array`? In other words, where is `Array(const Array& )`? You need that, otherwise you are not implementing the Rule of 3 fully and correctly. – PaulMcKenzie Sep 14 '19 at 04:48
  • Also, why in `main` are you doing this: `Array* arr = new Array(size, fill);` instead of `Array arr(size, fill);`? It seems your idea of how your code should work is not understood fully. In addition, this comment is not telling the truth: `//COPY CONSTRUCTOR TESTING` -- There is no copy constructor being used in that code. – PaulMcKenzie Sep 14 '19 at 04:55
  • Also you didn't include Array.h which might have some missing pieces – doug Sep 14 '19 at 04:57
  • Array* arr2 = new Array(); arr2 = arr; <— that code is not doing what you think it does. In particular it is not copying an Array object; rather it is just overwriting the arr2 pointer with the arr pointer (and causing a memory leak). Maybe do *arr2 = *arr; instead, or better yet avoid new/delete entirely and use only stack-objects. – Jeremy Friesner Sep 14 '19 at 05:02
  • Yes to what @JeremyFriesner mentioned. If you didn't use pointers, as mentioned in my second comment, implemented the copy constructor, then you would make some headway. Right now you are totally messing up `main` with the erroneous pointer usage, and you have an incomplete `Array` class, hoping it works correctly. – PaulMcKenzie Sep 14 '19 at 05:06
  • When you see a number that's super regular like 0xDDDDDDCD, it is probably something even more regular like 0xDDDDDDDD with an offset. Figure out that even more regular number and look it up to see if it means something. According to Wikipedia's page of [magical debugging numbers](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_debug_values), you're probably messing around with memory that has been freed. – user4581301 Sep 14 '19 at 05:15
  • 0xCD is the pattern for uninitialized heap memory and 0xDD is the pattern for freed heap memory. [When and why will an OS initialise memory to 0xCD, 0xDD, etc. on malloc/free/new/delete?](https://stackoverflow.com/q/370195/995714), [In Visual Studio C++, what are the memory allocation representations?](https://stackoverflow.com/q/127386/995714) – phuclv Sep 14 '19 at 09:00
  • The header file was provided and is fine. I was given a template for the methods in Array.cpp and just had to fill them in. The "Copy Constructor testing" was suppose to be a "operator = overload testing". I've updated this as well as added the code I had for the default constructor. It was early when I posted this so there were some mistakes. I apologize. – bonzi Sep 14 '19 at 19:25

1 Answers1

0

When you do arr2 = arr; you copy the pointer (memorty address) hold by arr into arr2:

Array* arr2 = new Array();
arr2 = arr;

So after that call, both arr2 and arr hold the same pointer (point to the same object). As of that delete arr2; will delete the same object you already deleted when you did delete arr; two lines before:

delete arr;
arr = nullptr;
delete arr2;

So doing delete arr2; here causes already undefine behavior. At that point, anything could happen.

t.niese
  • 39,256
  • 9
  • 74
  • 101