尝试运行代码时,堆已损坏

时间:2015-11-15 20:21:42

标签: c++ arrays operator-overloading

当我运行我的程序时,它会中断并且在调试程序时出现错误“堆已经损坏”,它实际上将完成整个事情并且在系统中断(“PAUSE”),这似乎是一个奇怪的地方有错误。问题所在,我一无所知。程序运行得很好,直到我为+和OS

添加了运算符重载

以下是我的代码:

的main.cpp

#include "stdafx.h"
#include "vector.h"

// the printV function
// used to test the copy constructor
// parameter: a MyVector object

void printV(Vector);


int main()
{
    cout << "\nCreating a vector Sam of size 4.";
    Vector sam(4);

    cout << "\nPush 12 values into the vector.";
    for (int i = 0; i < 12; i++)
        sam.push_back(i);

    cout << "\nHere is sam: ";
    cout << sam;
    cout << "\n---------------\n";

    cout << "\nCreating a vector Joe of size 4.";
    Vector joe(4);
    cout << "\nPush 6 values into the vector.";
    for (int i = 0; i < 6; i++)
        joe.push_back(i * 3);

    cout << "\nHere is joe: ";
    cout << joe;
    cout << "\n---------------\n";

    cout << "\nTest the overloaded assignment operator \"joe = sam\": ";
    joe = sam;

    cout << "\nHere is sam: ";
    cout << sam;
    cout << "\n---------------\n";

    cout << "\nHere is joe: ";
    cout << joe;
    cout << "\n---------------\n";

    // pass a copy of sam by value
    printV(sam);

    system("PAUSE");
    return 0;
}

void printV(Vector v)
{
    cout << "\n--------------------\n";
    cout << "Printing a copy of a vector\n";
    cout << v;
}

VECTOR.H

#pragma once
#include <iostream>
#include "stdafx.h"

using namespace std;

class Vector
{

private:
    int vectorSize;
    int vectorCapacity;
    int *vectorArray;

public:

    //A default constructor that creates an vector with a default capacity of 2
    Vector();

    //A parameterized constructor that creates a vector of capacity n
    Vector(int n);

    // A function, size(), that returns the size of your vector.
    int size();

    // A function, capacity(), that returns the capacity of the vector.
    int capacity();

    // A function, clear(), that deletes all of the elements from the vector and resets its size to zero and its capacity to two.
    void clear();

    // A function push_back(int n) that adds the integer value n to the end of the vector.If the vector is not large enough to hold this additional value, you must make the vector grow.Your grow algorithm should double the current capacity of the vector.Don't forget to consider the case where the initial capacity of the vector is zero.
    void push_back(int n);

    // A function at(int n) that returns the value of the element at position n in the vector.If the index n is greater than the size() of the vector, this function should throw an exception.
    int at(int n);

    friend ostream& operator<<(ostream& os, Vector vt);

    Vector operator=(Vector&);

VECTOR.CPP

#include "stdafx.h"
#include "vector.h"


Vector::Vector()
{
    vectorSize = 0;
    vectorCapacity = 0;
    vectorArray = 0;

}
// Create new array with given capacity
Vector::Vector(int n) 
{
    vectorCapacity = n;

    vectorArray = new int[vectorCapacity];

}
//Return array size
int Vector::size() 
{
    return vectorSize;
}

// Return array capacity
int Vector::capacity()
{
    return vectorCapacity;
}

// clear array values
void Vector::clear()
{
    for (int i = 0; i < sizeof(vectorArray); i++)
    {
        vectorArray[i] = '\0';
    }

    vectorSize = 0;
    vectorCapacity = 2;
}


// Add number to array and double array size if needed

void Vector::push_back(int n)
{
    int test = 100;
    if (vectorCapacity > vectorSize)
    {
        vectorArray[vectorSize] = n;
        vectorSize++;

    }
    else {

        if (vectorCapacity == 0) {
            vectorArray = new int[4];
            vectorArray[0] = n;
            vectorCapacity = 4;
            vectorSize++;
        }
        else {

            int newCapacity = vectorCapacity * 2;

            // Dynamically allocate a new array of integers what is somewhat larger than the existing array.An algorithm that is often used is to double the size of the array.

            int *tempArray = new int[newCapacity];

            // Change capacity to be the capacity of the new array.

            vectorCapacity = newCapacity;

            // Copy all of the numbers from the first array into the second, in sequence.

            for (int i = 0; i < Vector::size(); i++)
            {
                tempArray[i] = vectorArray[i];
            }

            delete[] vectorArray;
            vectorArray = new int[newCapacity];

            for (int i = 0; i < Vector::size(); i++)
            {
                vectorArray[i] = tempArray[i];
            }

            delete[] tempArray;

            // Add the new element at the next open slot in the new array.

            vectorArray[vectorSize] = n;

            // Increment the size;

            vectorSize++;

        }
    }
}


// Return Value and given point in array

int Vector::at(int n)
{
    return vectorArray[n];
}

// Cout Vector
ostream& operator<<(ostream& os, Vector vt)
{
    int size = vt.size();

    for (int i = 0; i < size; i++) {

        os << "index " << i << " is " << vt.at(i) << endl;

    }

    return os;
}

// Set one vector to equil another
Vector Vector::operator=(Vector& right) {

    // Clear array on left
    for (int i = 0; i < sizeof(vectorArray); i++)
    {
        vectorArray[i] = '\0';
    }

    vectorSize = right.size();
    vectorCapacity = right.size() * 2;

    // Assign values from left to right
    for (int i = 0; i < vectorSize; i++)
    {
        vectorArray[i] = right.at(i);
    }

    return vectorArray[0];

}

3 个答案:

答案 0 :(得分:2)

问题是operator=()

为什么?

您从sam开始,容量为4.您可以推回其中的12个项目。当你到达第5个元素时,容量从4增加到8然后你到达第9个元素,容量增加到24个。

然后你有joe,初始容量为4.你可以推回其中的6个项目。当你到达第5个元素时,它的容量会增加到8个。

当您执行joe = sam时,您的运营商会覆盖joe的大小和容量,但不会验证容量匹配,也不会分配丢失的容量。当你尝试在一个实际上只有8的容量的向量中复制12个元素时,你会在内存中做一些附带的破坏并破坏堆。

解决方案

不要盲目覆盖容量。如果足够的话,保持容量。如果没有,请调整容量并重新分配。

// Set one vector to equal another
Vector Vector::operator=(Vector& right) {

    //...    

    if (vectorCapacity < right.vectorCapacity) {
        delete[] vectorArray;   // assuming pointer is either nullptr or valid array
        vectorArray = new int[right.vectorCapacity];
        vectorCapacity = right.vectorCapacity;   
    }
    vectorSize = right.size();

    // Assign values from left to right
    //...

    return *this;
}

请注意,最好通过引用返回向量!

答案 1 :(得分:1)

有很多错误,但导致所述症状的错误是operator=永远不会为int分配vectorArray的新数组

每次使用sizeof(vectorArray)也是错误的。这只是指针的大小,而不是指向的区域的分配。

vectorArray[i] = '\0';的每一个地方都是毫无意义的,无论意图是什么,这都是错误的做法。够了,我甚至无法猜出意图。

clear函数中,唯一必要的步骤是vectorSize = 0;其余的一点是毫无意义的。设置容量为2有奇怪,虽然它没有什么大的危害。

operator=应该有返回类型Vector&而不是Vector,并且应该返回*this而不是构建一个Vector,其容量是旧版本的值。通常,类的几乎任何operator=成员都应返回*this。该规则的例外情况超出了您目前正在尝试学习的水平。

答案 2 :(得分:0)

鉴于目前为止的所有答案,另一个问题是您未能实现用户定义的复制构造函数:

Vector(const Vector& n);

由于函数按值返回Vector,因此必须正确实现此函数。由于您没有实现它,复制将无法正常工作。

第二个问题是您应该通过引用返回Vector,而不是operator=函数中的值。

我的第一个建议是在你的operator=中获取你现在拥有的任何代码,并在复制构造函数中完成“真实”复制的工作。以下是复制构造函数的简化版本:

#include <algorithm>
//..
Vector::Vector(const Vector& rhs) : vectorCapacity(rhs.vectorCapacity), 
                                    vectorArray(new int[rhs.vectorCapacity]), 
                                    vectorSize(rhs.size())
{
    std::copy(rhs.vectorArray, rhs.vectorArray + rhs.vectorCapacity, vectorArray);
}

请注意member initialization list的使用,以及对函数std::copy的调用(您也可以编写一个循环,但只是为了向您展示有无需手动执行复制的函数 - 书面循环)。

第二件事是你的析构函数应该只是这样做:

Vector::~Vector()
{  delete [] vectorArray; }

然后使用operator= copy / swap变得非常简单。

#include <algorithm>
//...
Vector& operator=(const Vector& v)
{
   Vector temp = v;
   swap(this.vectorCapacity, temp.vectorCapacity);
   swap(this.vectorArray, temp.vectorArray);
   swap(this.vectorSize, temp.vectorSize);
   return *this;
}

仅当复制构造函数和析构函数正常工作时才有效,因为operator=利用了这些函数。

详细了解Rule of 3copy / swap idiom