IntegerSet类堆内存损坏错误原因及修复方案咨询
修复IntegerSet类的堆内存损坏与功能异常问题
核心问题分析与修复步骤
1. 无参构造创建空集合导致越界访问
unionOfSets和intersectionOfSets中,原代码用new IntegerSet()创建默认size为0的集合,但后续插入原集合的元素(索引0~2)时,会直接访问超出数组范围的内存,触发堆损坏。
修复:创建新集合时取两个输入集合的最大size,确保能容纳所有可能的元素:
IntegerSet* IntegerSet::unionOfSets(const IntegerSet &otherSet) const { int newSize = max(setSize, otherSet.setSize); IntegerSet* thirdSet = new IntegerSet(newSize); for (int i = 0; i < newSize; ++i) { bool thisHas = (i < setSize) ? (setArray[i] == 1) : false; bool otherHas = (i < otherSet.setSize) ? (otherSet.setArray[i] == 1) : false; if (thisHas || otherHas) { thirdSet->insertElement(i); } } return thirdSet; } IntegerSet* IntegerSet::intersectionOfSets(const IntegerSet &otherSet) const { int newSize = max(setSize, otherSet.setSize); IntegerSet* extraSet = new IntegerSet(newSize); for (int i = 0; i < newSize; ++i) { bool thisHas = (i < setSize) ? (setArray[i] == 1) : false; bool otherHas = (i < otherSet.setSize) ? (otherSet.setArray[i] == 1) : false; if (thisHas && otherHas) { extraSet->insertElement(i); } } return extraSet; }
2. 元素操作的索引边界错误
原insertElement和deleteElement中,判断条件k <= setSize允许访问数组的越界索引(数组有效索引为0~setSize-1),直接导致堆内存损坏。
修复:将条件改为k < setSize:
bool IntegerSet::insertElement(int k) { if (k < setSize && k >= 0) { setArray[k] = 1; return true; } else return false; } bool IntegerSet::deleteElement(int m) { if (m < setSize && m >= 0) { setArray[m] = 0; return true; } else return false; }
3. isEqual函数的逻辑漏洞
原函数未判断两个集合的size是否相等,直接比较元素,导致size不同的集合可能被误判为相等。
修复:先判断size是否一致,再比较元素:
bool IntegerSet::isEqual(const IntegerSet &otherSet) const { if (setSize != otherSet.setSize) return false; for (int i = 0; i < setSize; ++i) { if (setArray[i] != otherSet.setArray[i]) return false; } return true; }
4. 测试代码的冗余操作
测试代码中while循环已完成有效插入,后续重复调用insertElement属于冗余,直接删除即可。
修复后的完整代码
头文件(IntegerSet.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
源文件(IntegerSet.cpp)
#include "IntegerSet.h" #include <iostream> #include <algorithm> using namespace std; IntegerSet::IntegerSet(int size) { setArray = new int[size]; setSize = size; for (int i = 0; i < size; ++i) { setArray[i] = 0; } } IntegerSet::IntegerSet(const IntegerSet &setToCopy) : setSize(setToCopy.setSize) { setArray = new int[setSize]; for (int i = 0; i < setSize; ++i) { setArray[i] = setToCopy.setArray[i]; } } IntegerSet::~IntegerSet() { delete[] setArray; } void IntegerSet::printSet() const { bool hasElements = false; for (int i = 0; i < setSize; ++i) { if(setArray[i] == 1) { cout << i + 1 << " "; hasElements = true; } } if (!hasElements) cout << "Empty"; } IntegerSet* IntegerSet::unionOfSets(const IntegerSet &otherSet) const { int newSize = max(setSize, otherSet.setSize); IntegerSet* thirdSet = new IntegerSet(newSize); for (int i = 0; i < newSize; ++i) { bool thisHas = (i < setSize) ? (setArray[i] == 1) : false; bool otherHas = (i < otherSet.setSize) ? (otherSet.setArray[i] == 1) : false; if (thisHas || otherHas) { thirdSet->insertElement(i); } } return thirdSet; } IntegerSet* IntegerSet::intersectionOfSets(const IntegerSet &otherSet) const { int newSize = max(setSize, otherSet.setSize); IntegerSet* extraSet = new IntegerSet(newSize); for (int i = 0; i < newSize; ++i) { bool thisHas = (i < setSize) ? (setArray[i] == 1) : false; bool otherHas = (i < otherSet.setSize) ? (otherSet.setArray[i] == 1) : false; if (thisHas && otherHas) { extraSet->insertElement(i); } } return extraSet; } bool IntegerSet::insertElement(int k) { if (k < setSize && k >= 0) { setArray[k] = 1; return true; } else return false; } bool IntegerSet::deleteElement(int m) { if (m < setSize && m >= 0) { setArray[m] = 0; return true; } else return false; } bool IntegerSet::isEqual(const IntegerSet &otherSet) const { if (setSize != otherSet.setSize) return false; for (int i = 0; i < setSize; ++i) { if (setArray[i] != otherSet.setArray[i]) return false; } return true; }
测试文件(main.cpp)
#include "IntegerSet.h" #include <iostream> using namespace std; int main() { int 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; } cout << "Enter a number between 1 and 3 to add to the second set: "; cin >> input; while (!set2.insertElement(input - 1)) { cout << "\nThat is an invalid number. Please enter a number between 1 and 3: "; cin >> input; } cout << "Set 1 is: {"; set1.printSet(); cout << "}\nSet 2 is: {"; set2.printSet(); cout << "}\n" << endl; set3 = set1.unionOfSets(set2); set4 = set1.intersectionOfSets(set2); cout << "The union of Set 1 and Set 2: " << endl; cout << "Set 3 - {"; set3->printSet(); cout << "}" << endl; cout << "The intersection of Set 1 and Set 2: " << endl; cout << "Set 4 - {"; set4->printSet(); 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 << "\nAfter 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; }
内容的提问来源于stack exchange,提问作者Joe Forsyth
相关产品推荐
相关产品推荐

