尝试运行代码时堆已损坏

A heap has been corrupted when trying to run code

本文关键字:已损坏 代码 试运行      更新时间:2023-10-16

当我运行我的程序时,它会中断并在调试程序时出现错误"堆已损坏",它实际上会很好地完成整个过程并在系统上中断("暂停"(,这似乎是一个奇怪的地方出现错误。我不知道问题出在哪里。该程序运行良好,直到我为 + 和操作系统添加了运算符重载

下面是我的代码:

主要。.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 vectorn";
    cout << v;
}

向量。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&);

向量。.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] = '';
    }
    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] = '';
    }
    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];
}

问题是operator=()

为什么?

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

然后,您将拥有初始容量为 4 的joe。 你推回其中的 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;
}

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

有很多错误,但导致所描述症状的错误是operator=从未为vectorArray分配新的int数组

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

每个做vectorArray[i] = '';的地方充其量是毫无意义的,无论意图如何,这都是错误的方式。 足够了,所以我什至无法猜测意图。

clear函数中,唯一必要的步骤是vectorSize = 0;其余的步骤充其量是毫无意义的。 将容量设置为 2 很奇怪,尽管它没有重大危害。

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

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

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

请注意成员初始化列表的用法,以及对函数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=利用了这些函数。

阅读更多关于 3 法则和复制/交换习语的信息。