Ошибка исключение: нарушение прав доступа для чтения месте 0xDDDDDDDD

Я пытаюсь создать динамический строковый массив в c++. При попытке отобразить содержимое моего массива динамических строк на консоли я получаю эту ошибку:

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

вот мой код:

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;
}

может кто-нибудь сказать мне, что я делаю неправильно. Как я могу решить эту проблему?

1 ответов


обратите внимание, что все это уже доступно с помощью std::vector<std::string>. The std:: vector class-это класс динамического массива, который предоставляет C++, и нет причин делать домашние версии того, что доступно вам.


сказав это, одна вопиющая проблема заключается в том, что ваш конструктор копирования неверен. The dynamicArray инициализирован, но вы используете его здесь:

if (dynamicArray != NULL)

нет никакой гарантии, что значение dynamicArray есть. Исправление состоит в том, чтобы удалить весь этот блок кода в конструкторе копирования:

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

поскольку конструктор копирования создает совершенно новый объект, нет причин "предварительно" для нулевого указателя и, таким образом, делать ненужную работу. Помните, что объект не существовал, поэтому ничего предварительного делать не нужно.


вторая проблема заключается в том, что вы выдав delete [] temp; вызов в addEntry и deleteEntry функции. Удалите эти строки, как вы освобождение памяти, которую вы только что назначили dynamicArray.


третья проблема заключается в том, что отсутствует определяемый пользователем оператор присваивания. Оператор присваивания имеет следующую подпись, и вам необходимо обеспечить реализацию:

DynamicStringArray& operator=(const DynamicStringArray& );

без этой функции, назначение DynamicStringArray в другой DynamicStringArray приведет к утечкам памяти и двойному освобождению памяти, когда оба объекта выйдут из области видимости.

одна реализация может используйте копировать / обмен идиоматическое выражение:

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

другой вопрос заключается в следующем:

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

это неопределенное поведение для назначения std::string объект с NULL. Либо верните пустую строку, либо создайте исключение, если индекс выходит за рамки.


в заключение, я настоятельно рекомендую вам прочитать о Правило 3 когда дело доходит до разработки классов, которые должны реализовать правильную семантику копирования.