Exception Error : Access violation reading location 0xDDDDDDDD

14,483

Please note that all of this is already available by utilizing std::vector<std::string>. The std::vector class is the dynamic array class that C++ provides, and there is little to no reason to make home-made versions of what is available to you.


Having said this, one glaring issue is that your copy constructor is incorrect. The dynamicArray is uninitialized, but you use it here:

if (dynamicArray != NULL)

There is no guarantee what value dynamicArray has. The fix is to remove this entire block of code in the copy constructor:

if (dynamicArray != NULL)
{
    size = 0;
    delete [] dynamicArray;
    dynamicArray = NULL;
}

Since the copy constructor constructs a brand new object, there is no reason to "pretest" for a NULL pointer and thus do unnecessary work. Remember that the object did not exist, so there is nothing preliminary to do.


The second issue is that you're issuing a delete [] temp; call in the addEntry and deleteEntry functions. Remove these lines, as you are deallocating the memory that you've just assigned to dynamicArray.


The third issue is that you're missing the user-defined assignment operator. The assignment operator has the following signature, and you need to provide the implementation:

DynamicStringArray& operator=(const DynamicStringArray& );

Without this function, assigning a DynamicStringArray to another DynamicStringArray will cause memory leaks and double deallocation of memory when both objects go out of scope.

One implementation can use the copy / swap idiom:

#include <algorithm>
//...
DynamicStringArray& DynamicStringArray::operator=(const DynamicStringArray& rhs)
{
    DynamicStringArray temp(rhs);
    std::swap(temp.dynamicArray, dynamicArray);
    std::swap(temp.size, size);
    return *this;
}

Another issue is this:

string DynamicStringArray::getEntry(int index)
{
    if ((index >= 0) && (index < size))
    {
        return dynamicArray[index];
    }
    return NULL;  // <-- Undefined behavior if this is done
}

It is undefined behavior to assign a std::string object with NULL. Either return an empty string, or throw an exception if the index is out of bounds.


In conclusion, I highly recommend that you read up on the Rule of 3 when it comes to designing classes that must implement correct copy semantics.

Share:
14,483
mtcode
Author by

mtcode

Updated on August 11, 2022

Comments

  • mtcode
    mtcode over 1 year

    I am trying to create a dynamic string array in c++. When trying to display the contents of my dynamic string array to the console I receive this error:

    Exception thrown at 0x0FD670B6 (msvcp140d.dll) in Assignment4.exe: 0xC0000005: Access violation reading location 0xDDDDDDDD.
    

    Here is my code:

    DynamicStringArray.h

    #pragma once
    #include "stdafx.h"
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    class DynamicStringArray
    {
    public:
        DynamicStringArray();
        DynamicStringArray(DynamicStringArray &array);
        ~DynamicStringArray();
        int getSize();
        void displayContents();
        void addEntry(const string &addElement);
        string getEntry(int index);
        int deleteEntry(const string &deleteElement);
    
    private: 
        string *dynamicArray;
        int size;
    };
    

    DynamicStringArray.cpp

    #include "stdafx.h"
    #include "DynamicStringArray.h"
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    DynamicStringArray::DynamicStringArray()
    {
        dynamicArray = NULL;
        size = 0;
    }
    
    DynamicStringArray::DynamicStringArray(DynamicStringArray &array)
    {
        if (dynamicArray != NULL)
        {
            size = 0;
            delete [] dynamicArray;
            dynamicArray = NULL;
        }
    
        size = array.getSize();
        dynamicArray = new string[size];
        for (int i = 0; i < size; i++)
            dynamicArray[i] = array.dynamicArray[i];
    }
    
    DynamicStringArray::~DynamicStringArray()
    {
        cout << "In destructor." << endl;
        delete [] dynamicArray;
        dynamicArray = NULL;
    }
    
    int DynamicStringArray::getSize()
    {
        return size;
    }
    
    void DynamicStringArray::displayContents()
    {
        if (size != 0)
            for (int i = 0; i < size; i++)
                cout << "Item-" << i << ": " << dynamicArray[i] << endl;
        else
            cout << "Array is empty." << endl;
    }
    
    void DynamicStringArray::addEntry(const string &addElement)
    {
        string *temp = new string[size + 1];
        for (int i = 0; i < size; i++)
                temp[i] = dynamicArray[i];
        temp[size] = addElement;
        size++;
        delete [] dynamicArray;
        dynamicArray = temp;
        delete[] temp;
    }
    
    string DynamicStringArray::getEntry(int index)
    {
        if ((index >= 0) && (index < size))
        {
            return dynamicArray[index];
        }
        return NULL;
    }
    
    int DynamicStringArray::deleteEntry(const string &deleteElement)
    {
        if(size == 0)
        {
            return false;
        }
    
        for (int i = 0; i < size; i++)
        {
            if (dynamicArray[i] == deleteElement)
            {
                string *temp = new string[size - 1];
                for (int x = 0; x < size - 1; ++x)
                {
                    if (x < i)
                        temp[x] = dynamicArray[x];
                    else
                        temp[x] = dynamicArray[x + 1];
                }
    
                delete[] dynamicArray;
                dynamicArray = temp;
                delete[] temp;
                --size;
                return true;
            }
        }
    
        return false;
    }
    

    main:

    int main()
    {
        DynamicStringArray dsArray1;
        cout << "dsArray1.displayContents():" << endl;
        dsArray1.displayContents();  // Should indicate array is empty
        cout << "Display dsArray1.getSize()= " << dsArray1.getSize() << endl;
    
        dsArray1.addEntry("Entry-A");
        dsArray1.displayContents();
    
        dsArray1.addEntry("Entry-B");
        dsArray1.displayContents();
        dsArray1.addEntry("Entry-C");
        dsArray1.displayContents();
        return 0;
    }
    

    Can anyone tell me what I am doing wrong. How can i fix this problem?

  • Miles Budnek
    Miles Budnek over 8 years
    The assignments in addEntry are all std::strings, so they're fine (implementing an operator= would still probably be a good idea). The problem there is with the last line delete[] temp;
  • PaulMcKenzie
    PaulMcKenzie over 8 years
    @MilesBudnek I updated the answer to point out the issue with both addEntry and deleteEntry.