glibc检测到错误,可能是内存泄漏?

时间:2015-05-28 03:04:53

标签: c++ class memory-leaks runtime-error glibc

头文件(IntegerSet.h)

#include<iostream>
#include<string>
using namespace std;
class IntegerSet{
public:
 unsigned int set[15];
 unsigned int empty_set[15];
 IntegerSet();
 IntegerSet(int[],int);
 IntegerSet unionOfsets(IntegerSet);
 IntegerSet intersectionOfSets(IntegerSet);
 void insertElement(int);
 void deleteElement(int);
 void printSet();
 bool isEqualTo(IntegerSet);
 void emptySet();//Set all elements of set to 0
 void inputSet();//Reads values from the user into set
 bool validEntry(int);//Determines a valid entry to the set
 };

实施文件(IntegerSet.cpp)

//Class implementation file
#include "IntegerSet.h"
using namespace std;

IntegerSet::IntegerSet(){
for(int i=0;i<100;i++){
empty_set[i]=0;
}
}

IntegerSet::IntegerSet(int arr[],int size){
int min;//Use to hold the value for the sorting algorithm
int counter;//Used to count how many values need to be removed from the new  array
for(int i=0;i<size-1;i++){//Nested for loop used to sort the array in ascending order
min=arr[i];
if(arr[i]<0||arr[i]>100){//If statement used to count how many numbers are <0 or >100
  counter++;
}
for(int k=i+1;k<size;k++){
  if(arr[k]<min){
    arr[i]=arr[k];
    arr[k]=min;
    min=arr[i];
  }
}
}
int *newSet=new int[size-counter];
for(int j=0;j<size;j++){
if(arr[j]>100||arr[j]<0){
  //Do nothing
}else{

  newSet[j]=arr[j];
}
}
delete newSet;
}
bool IntegerSet::validEntry(int a){
if(a<0||a>100){
return false;
}
return true;
}

void IntegerSet::inputSet(){
int a;
for(int i=0;i<100;i++){
cout<<"Enter an element(-1 to end)";
cin>>a;
if(a==-1){
cout<<"Entry complete";
return;
}
this->set[i]=a;
}
}

void IntegerSet::emptySet(){

for(unsigned int i=0;i<sizeof(this->set);i++){
this->set[i]=0;
}
}

IntegerSet IntegerSet::unionOfsets(IntegerSet a){
unsigned int *Union=new unsigned int[sizeof(this->set)+sizeof(a.set)];
for(unsigned int i=0;i<sizeof(this->set);i++){
*(Union+i)=this->set[i];
for(unsigned int h=0;h<sizeof(this->set);h++){
  *(Union+(h+i))=a.set[h];
  }
 }
for(unsigned int j=0;j<sizeof(*Union);j++){
for(unsigned int z=j+1;z<sizeof(*Union);z++){
  if(*(Union+j)==*(Union+z)){
    *(Union+z)=0;
  }
}
}
unsigned int newUnion[sizeof(*Union)];
for(unsigned int y=0;y<sizeof(*Union);y++){
if(*(Union+y)!=0&&y<sizeof(newUnion)){
  newUnion[y]=*(Union+y);
}
}
IntegerSet c;
for(unsigned int w=0;w<sizeof(*Union);w++){
c.set[w]=newUnion[w];
}
delete Union;
return c;
}

IntegerSet IntegerSet::intersectionOfSets(IntegerSet a){
unsigned  int *Intersect=new unsigned int[sizeof(this->set)+sizeof(a.set)];
int counter=0;
for(unsigned int i=0;i<sizeof(this->set);i++){
for(unsigned int j=0;j<sizeof(a.set);j++){
  if(this->set[i]==a.set[j]){
    *(Intersect+counter)=a.set[j];
    counter++;
  }
}
}
IntegerSet c;
for(unsigned int w=0;w<sizeof(*Intersect);w++){
c.set[w]=*(Intersect+w);
}
delete Intersect;
return c;
}

void IntegerSet::printSet(){
unsigned int min;
for(unsigned int i=0;i<sizeof(this->set)-1;i++){
min=this->set[i];
for(unsigned int k=i+1;k<sizeof(this->set);k++){
{
  if(this->set[k]<min){
    this->set[i]=this->set[k];
    this->set[k]=min;
    min=this->set[i];
  }
}
}
cout<<"{";
for(unsigned int h=0;h<3;h++){
if(h==sizeof(this->set)-1){
  cout<<this->set[h]<<"}";
}else{
  cout<<this->set[h]<<",";
}
}

}

bool IntegerSet::isEqualTo(IntegerSet a){
unsigned int counter=0;
if(sizeof(a.set)==sizeof(this->set)){
for(unsigned int i=0;i<sizeof(this->set);i++){
  for(unsigned int f=0;f<sizeof(a.set);f++){
    if(this->set[i]==a.set[f]){
      counter++;
    }
  }
 }
}else{
return false;
}
if(counter==sizeof(this->set)){
return true;
}
return false;//Used to make sure this method always has something to return
}

void IntegerSet::insertElement(int a){
unsigned A=(unsigned)a;
if(!this->validEntry(a)){
  cout<<"Invalid Insertion Attempt!";
}
unsigned int Inserted[sizeof(this->set)+1];
Inserted[sizeof(this->set)]=A;
for(unsigned int w=0;w<sizeof(Inserted);w++){
this->set[w]=Inserted[w];
}
}

void IntegerSet::deleteElement(int a){
unsigned A=(unsigned) a;
unsigned int *Delete=new unsigned int[sizeof(this->set)-1];int test=0;
if(!this->validEntry(a)){
cout<<"No value of: "<<a<<" exists in the set";
}
for(unsigned int z=0;z<sizeof(this->set);z++){
if(this->set[z]==A){
  test++;
}
}
if(test==0){
cout<<"No value of: "<<a<<" exists in the set";
}
for(unsigned int i=0;i<sizeof(this->set)-1;i++){
*(Delete+i)=this->set[i];
}
for(unsigned int w=0;w<sizeof(*Delete);w++){
this->set[w]=*(Delete+w);
}
delete Delete;
 }

然后是我的测试人员文件,这是让我找到错误的原因 (IntSet.cpp)

//Driver program for class IntegerSet
#include <iostream>
using namespace std;

#include "IntegerSet.h"

int main(){
IntegerSet a,b,c,d;
cout<<"Enter set A:\n";
 a.inputSet();
 cout<<"\nEnter set B:\n";
 b.inputSet();
 c=a.unionOfsets(b);
 d=a.intersectionOfSets(b);
 cout<<"\nUnion of A nd B is:\n";
 c.printSet();
 cout<<"Intersection of A nd B is:\n";
 d.printSet();

 //Test if set A is equal to set B
 if(a.isEqualTo(b)){
 cout<<"Set A is equal to set B\n";
 }else{
 cout<<"Set A is not equal to set B\n";
 }

 //test insertion
 cout<<"\nInserting 77 into set A...\n";
  a.insertElement(77);
 cout<<"Set A is now:\n";
 a.printSet();

 const int arraySize=10;
 int intArray[arraySize]={25,67,2,9,99,105,45,-5,100,1};
 //Use construct that receive an array of ints
 //and the size of that array to create a set object
 IntegerSet e(intArray,arraySize);

 cout<<"\nSet e is:\n";
 e.printSet();
 cout<<endl;

 }

就我个人而言,我觉得导致这个错误的原因是某种内存泄漏,虽然glib c错误并没有像编译器那样准确地告诉我它将来自何处。此函数也会在函数b.inputSet()退出后立即发生。

错误说的是什么(它在我注意到的两条消息之间交替出现):

***glibc detected*** ./a.out: free(): invalid next size (normal): 
***glibc detected*** ./a.out: double free or corruption (!prev):

2 个答案:

答案 0 :(得分:1)

你在这里做得很多。

以下是empty_set的定义。

 unsigned int empty_set[15];

你的默认构造函数访问这些边界之外。

IntegerSet::IntegerSet(){
    for(int i=0;i<100;i++){
        empty_set[i]=0;
    }
}

你的其他构造函数实际上没有改变类中的任何内容。

此代码

IntegerSet IntegerSet::unionOfsets(IntegerSet a){
    unsigned int *Union=new unsigned int[sizeof(this->set)+sizeof(a.set)];

看起来非常可疑,因为sizeof(set)不是集合中的元素数量,而是数组长度(以字节为单位)(15 * sizeof(float)) - 但如果切换到可变长度数组,它甚至不会......您需要分别跟踪设定的长度。或者使用std::vector<int>,或者更好 - 为什么重新发明轮子并使用std::set<int>

答案 1 :(得分:0)

删除数组时,需要告诉delete它是一个数组

所以

int *newSet = new int[size - counter];

需要使用

删除
delete[] newSet;

可能还有几个。这是我发现的第一个。

当你有时间时,请查看Valgrind工具。它会给出非常详细的结果。