【问题标题】:glibc detected error, possible memory leak?glibc 检测到错误,可能存在内存泄漏?
【发布时间】:2015-05-28 03:04:53
【问题描述】:

头文件(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):

【问题讨论】:

  • Valgrind 在这些情况下非常有用。
  • “我个人觉得导致这个错误的原因是某种内存泄漏”——你的感觉完全不正确。在你有几年的经验之前,你应该拒绝关注自己的感受。
  • 这段代码有很多错误。我建议你在上面运行一个静态分析器,看看它抱怨什么。或者在此处将标头和实现复制并粘贴到在线检查器(DIY-C++ 选项)中:gimpel-online.com/OnlineTesting.html
  • 仅供参考 - 我在代码上运行了该检查器并收到了几页警告,其中大部分是关于 [] 的无效范围。但我不会把它们都贴在这里...
  • @MichaelAnderson 当我将头文件和实现文件复制并粘贴到在线检查器中时,它是否必须按任何特定顺序排列?它们是否都被粘贴到同一个区域中?谢谢你的帮助!抱歉,如果我问的问题太多。

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


【解决方案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&lt;int&gt;,或者更好——为什么要重新发明轮子并使用std::set&lt;int&gt;

【讨论】:

  • 啊,'sizeof(a.set)' 可能是问题所在,因为在整个代码中以类似的方式对它们进行了比较。相反,我想我会像你建议的那样用循环单独计算它们。我也不太清楚 'std::set' 的作用。
  • std::set&lt;int&gt; 是一组 int 值 - 支持您的 IntegerSet 所做的一切,但做得“正确”。
猜你喜欢
  • 2021-07-17
  • 2021-11-30
  • 2018-08-13
  • 2012-07-16
  • 2021-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多