尝试 运行 代码时堆已损坏
A heap has been corrupted when trying to run code
每当我 运行 我的程序在调试程序时中断并出现错误 "A heap has been corrupted" 时,它实际上会很好地完成整个过程并在系统上中断("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] = '[=13=]';
}
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] = '[=13=]';
}
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=
从未为 vectorArray
分配新的 int
数组
每次使用sizeof(vectorArray)
也是错误的。那只是指针的大小,而不是指向的区域的分配。
每个做 vectorArray[i] = '[=14=]';
的地方充其量是毫无意义的,无论是什么意图,那都是错误的做法。够了,我什至猜不到意图。
在 clear
函数中唯一必要的步骤是 vectorSize = 0;
其余的充其量是毫无意义的。将 capacity 设置为 2 是很奇怪的,尽管它不会造成重大伤害。
operator=
应该 return 键入 Vector&
而不是 Vector
并且 return *this
不应该构造 Vector
其容量是旧容量的值。一般来说,class 的几乎所有 operator=
成员都应该 return *this
。该规则的例外情况远远超出您当前尝试学习的水平。
问题是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;
}
请注意,最好通过引用 return 向量!
鉴于目前的所有答案,另一个问题是您未能实现用户定义的复制构造函数:
Vector(const Vector& n);
此函数必须正确实现,因为您有按值返回 Vector
的函数。由于您没有实施,因此无法正常复制。
第二个问题是您应该通过引用返回 Vector
,而不是 operator=
函数中的值。
我的第一个建议是使用您现在在 operator=
中的任何代码,并在复制构造函数中完成 "real" 复制的工作。这是复制构造函数的简化版本:
#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 3 and the copy / swap idiom 的更多信息。
每当我 运行 我的程序在调试程序时中断并出现错误 "A heap has been corrupted" 时,它实际上会很好地完成整个过程并在系统上中断("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] = '[=13=]';
}
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] = '[=13=]';
}
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=
从未为 vectorArray
int
数组
每次使用sizeof(vectorArray)
也是错误的。那只是指针的大小,而不是指向的区域的分配。
每个做 vectorArray[i] = '[=14=]';
的地方充其量是毫无意义的,无论是什么意图,那都是错误的做法。够了,我什至猜不到意图。
在 clear
函数中唯一必要的步骤是 vectorSize = 0;
其余的充其量是毫无意义的。将 capacity 设置为 2 是很奇怪的,尽管它不会造成重大伤害。
operator=
应该 return 键入 Vector&
而不是 Vector
并且 return *this
不应该构造 Vector
其容量是旧容量的值。一般来说,class 的几乎所有 operator=
成员都应该 return *this
。该规则的例外情况远远超出您当前尝试学习的水平。
问题是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;
}
请注意,最好通过引用 return 向量!
鉴于目前的所有答案,另一个问题是您未能实现用户定义的复制构造函数:
Vector(const Vector& n);
此函数必须正确实现,因为您有按值返回 Vector
的函数。由于您没有实施,因此无法正常复制。
第二个问题是您应该通过引用返回 Vector
,而不是 operator=
函数中的值。
我的第一个建议是使用您现在在 operator=
中的任何代码,并在复制构造函数中完成 "real" 复制的工作。这是复制构造函数的简化版本:
#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 3 and the copy / swap idiom 的更多信息。