Exception Error : Access violation reading location 0xDDDDDDDD
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.
mtcode
Updated on August 11, 2022Comments
-
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 over 8 yearsThe assignments in
addEntry
are allstd::string
s, so they're fine (implementing anoperator=
would still probably be a good idea). The problem there is with the last linedelete[] temp;
-
PaulMcKenzie over 8 years@MilesBudnek I updated the answer to point out the issue with both
addEntry
anddeleteEntry
.