提问人:Joe Forsyth 提问时间:7/26/2023 最后编辑:Code_Sphinx_TSKJoe Forsyth 更新时间:7/28/2023 访问量:44
为什么我在 IntegerSet 类中收到堆损坏错误?
Why am I receiving a heap corruption error in IntegerSet class?
问:
我有一个作业,我必须创建一个名为 IntegerSet 的类。关键是它创建了整数集。如果集合中存在整数,则该数字在数组集中的位置为 1,如果没有,则为 0。我一直在研究动态内存分配,所以我认为我需要保留这部分。但是,当我运行该程序时,它允许我输入最多第二个数字。然后它会出现一个错误,关于堆内存损坏。我根本不知道如何解决它。我想也许我的某些方法中的内存范围可能会有点偏离。或者我的动态内存分配有其他问题。
由于在我的课堂上,我们正在研究动态内存分配、指针和按引用传递,我希望能够将这些方面保留在程序中,并学习如何使它们正常工作。
下面是 .h 文件:
#ifndef INTEGERSET_H
#define INTEGERSET_H
class IntegerSet
{
private:
int *setArray;
int setSize;
public:
IntegerSet(int = 0);
IntegerSet(const IntegerSet&);
~IntegerSet();
IntegerSet* unionOfSets(const IntegerSet&) const;
IntegerSet* intersectionOfSets(const IntegerSet&) const;
bool insertElement(int);
bool deleteElement(int);
void printSet() const;
bool isEqual(const IntegerSet&) const;
};
#endif
下面是 .cpp 文件:
#include "IntegerSet.h"
#include <iostream>
using namespace std;
//Constructor
IntegerSet::IntegerSet(int size)
{
setArray = new int[size];
setSize = size;
for (int i = 0; i < size; ++i)
{
setArray[i] = 0; //Initializes the set to 0;
}
}
//Copy constructor
IntegerSet::IntegerSet(const IntegerSet &setToCopy)
: setSize(setToCopy.setSize)
{
setArray = new int[setSize];
for (int i = 0; i < setSize; ++i)
{
setArray[i] = setToCopy.setArray[i];
}
}
//Destructor
IntegerSet::~IntegerSet()
{
delete[] setArray;
}
//Prints set
void IntegerSet::printSet() const
{
for (int i = 0; i < setSize; ++i)
{
if(setArray[i] == 1)
cout << i + 1 << " ";
}
}
//Unites two sets into a new set
IntegerSet* IntegerSet::unionOfSets(const IntegerSet &otherSet) const
{
IntegerSet* thirdSet = new IntegerSet; //Dynamically allocates a new set
for (int i = 0; i < setSize; ++i)
{
if (this->setArray[i] == 1 || otherSet.setArray[i] == 1)//
{
thirdSet->insertElement(i); //Assigns the new set the united sets' values
}
}
return thirdSet; //Returns pointer to new resulting set.
}
//Inyersects two sets to the new set
IntegerSet* IntegerSet::intersectionOfSets(const IntegerSet &otherSet) const
{
IntegerSet* extraSet = new IntegerSet;
for (int i = 0; i < setSize; ++i)
{
if (setArray[i] == 1 && otherSet.setArray[i] == 1)
{
extraSet->insertElement(i); //Assigns the new set the intersecting sets' values
}
}
return extraSet; //Returns pointer to the new resulting set
}
//Inseerts new element
bool IntegerSet::insertElement(int k)
{
if (k <= setSize && k >= 0)
{
setArray[k] = 1;
return true;
}
else
return false;
}
//Deletes element
bool IntegerSet::deleteElement(int m)
{
if (m <= setSize && m >= 0)
{
setArray[m] = 0;
return true;
}
else
return false;
}
//Checks if two sets are equal
bool IntegerSet::isEqual(const IntegerSet &otherSet) const
{
for (int i = 0; i < setSize; ++i) //Access each element
{
if (setArray[i] != otherSet.setArray[i])
return false; //If even one element is not equal then the sets cannot be equal
}
return true; //If after the loop finds none of the elements are equal, then the sets must be equal
}
下面是客户端测试文件:
#include "IntegerSet.h"
#include <iostream>
using namespace std;
int main()
{
int input; //User input
IntegerSet set1(3);
IntegerSet set2(3);
IntegerSet* set3 = nullptr;
IntegerSet* set4 = nullptr;
cout << "Enter a number between 1 and 3 to add to the first set: ";
cin >> input;
while (!set1.insertElement(input - 1))
{
cout << "\nThat is an invalid number. Please enter a number between 1 and 3: ";
cin >> input;
}
set1.insertElement(input - 1);
cout << "Enter a number between 1 and 3 to add to the first set: ";
cin >> input;
while (!set2.insertElement(input - 1))
{
cout << "\nThat is an invalid number. Please enter a number between 1 and 3: ";
cin >> input;
}
set2.insertElement(input - 1);
cout << "Set 1 is: ";
set1.printSet();
cout << "\nSet 2 is: ";
set2.printSet();
cout << endl;
set3 = set1.unionOfSets(set2);
set4 = set1.intersectionOfSets(set2);
cout << "The union of Set 1 and Set 2: " << endl;
cout << "Set 3 - {"; // I tried using this first:
set3->printSet(); //cout << "Set 1 - {" << set1.printSet() << "}" << endl;
cout << "}" << endl; // But it wouldn't work because the second << was being show as an ambiguity error
cout << "The intersection of Set 1 and Set 2: " << endl;
cout << "Set 4 - {";
set4->printSet(); //Same formatting reasons as above.
cout << "}" << endl;
if (set1.isEqual(set2))
cout << "Set 1 and Set 2 are equal" << endl;
else
cout << "Set 1 and Set 2 are not equal" << endl;
set3->deleteElement(1);
set4->deleteElement(1);
cout << "After removing 2 from Set 3 and Set 4" << endl
<< "Set 3 is now - {";
set3->printSet();
cout << "}" << endl;
cout << "Set 4 is now - {";
set4->printSet();
cout << "}" << endl;
delete set3;
delete set4;
system("PAUSE");
return 0;
}
该程序应该要求用户提供两个整数,只是为了测试。然后,它将做一些他们创建的集合的并集和交集的示例。最终发生的事情是,它会到达第二个输入,然后出现堆损坏错误,并且显示联合集的字符串不会打印。
答:
一个主要问题是在函数中,你创建了一个新集合,如下所示:unionOfSets
IntegerSet* thirdSet = new IntegerSet;
这意味着默认设置大小将为零。这意味着您在构造函数中创建的数组的大小为零。
然后调用时,您可以检查索引是否小于或等于设置的大小。这是真的,因为这是真的。insertElement
0 <= 0
因此,您将取消引用零大小数组的第一个元素。导致未定义的行为和可能的崩溃。
您需要为您创建的新集设置特定大小。并更新签入。insertElement
我还建议你停止使用指针和动态分配,就像你的代码一样。如果您正确地实现了 3 或 5 的规则,那么您可以毫无问题地复制和移动集合。
此外,除非它是作业或练习的一部分,否则请使用而不是您自己的数组处理,然后您可以改用零规则。std::vector<int>
评论
new IntegerSet(setSize)
评论
k <= setSize
应该是k < setSize
IntegerSet
main
IntegerSet
IntegerSet* IntegerSet::unionOfSets(const IntegerSet &otherSet) const
IntegerSet IntegerSet::unionOfSets(const IntegerSet &otherSet) const
intersectionOfSets
main