【问题标题】:segmentation fault in c++ with inheritance带有继承的c ++中的分段错误
【发布时间】:2014-03-01 08:39:09
【问题描述】:
#include<iostream>
#include<vector>  
#include "hashtable.h"

using namespace std;

class dummy
{
public:
int a;
vector<int> k;
dummy()
{
    a= 10;
    k.push_back(10);
    k.push_back(20);
}

~dummy()
{
    cout<<"clearing dummy"<<endl;
    k.clear();
    cout<<"comple"<<endl;
}
 };


class parent
{
public:
dummy *p;
Hashtable *nodes_hashtable;
parent()
{
    p = new dummy();
}

void create_nodes_hashtable();

virtual ~parent()
{
    cout<<"clearing parent"<<endl;
    delete(p);
    delete(nodes_hashtable);
}

 };


 //given the hashtable,updates the values in the hashtable
 void parent ::  create_nodes_hashtable()
{
nodes_hashtable = new(std::nothrow) Hashtable(500);

//check :if the hashtable has been created
if(NULL == nodes_hashtable)
{
    cout<<"out of memory"<<endl;
}

for(unsigned int i = 0;i<20 ;i++)
{       
    //normalising the key ,so that the key lies within the range of the hashtable
    int key = i;//get_nodes_hashtablekey(i,i);
    (*nodes_hashtable).add_element(key,i,i);
}
} 


class child: public parent
{
public:
  child()
  {
 }
 ~child()
 {
     cout<<"clearing child"<<endl;
}
};

int main()
{
 child c;
 cout<<"gng of scope"<<endl;
return(0);
}

Hashtable.h代码如下:

 #ifndef _HASHTABLE_H_
 #define _HASHTABLE_H_

 #include<vector>
 #include<iostream>
 #include<string> 
 #include<algorithm>
 //returns this value if the object corresponding to the key is not found in the hashtable
 #define NOT_FOUND_IN_HASHTABLE -1

 //default hashtable size
 //wen the size is not passed in the arguments
  #define DEFAULT_HASHTABLE_SIZE 200//WINDOW_LENGTH

  //defines the data structure hashtable
  //the hashtable assumes that each object_identifier refers to an unique object

  class Hashtable
  {

private :

//counts the number of elements added into the hashtable
unsigned int count_elements_added;

//counts the number of elements removed from the hashtable
unsigned int count_elements_removed;

//counts the number of elements present in the hashtable
unsigned int count_elements_present;

//sets the size of the hashtable
unsigned int hashtable_size;

//the data structure (vector) that contains the objects
 //the position on the hastable is defined by 2 keys
 //one the position in the array of the hashtable : the start of the node is used
//the second is the first element in the pair present in the hash table //end of the node is used
std :: vector< std :: vector<std :: pair<int,int> > > hashtable;

//intialize the hashtable
 void intialize_hashtable();

//checks whether the hashtable is corrupted or not
 //returns true,if the hashtable is corrupted
//else returns false
 bool is_corrupt();

 public :

Hashtable()
{
    hashtable_size = DEFAULT_HASHTABLE_SIZE;
    hashtable.clear();
    intialize_hashtable();

    //counts the number of elements added into the hashtable
    count_elements_added = 0;

    //counts the number of elements removed from the hashtable
    count_elements_removed = 0;

    //counts the number of elements present in the hashtable
    count_elements_present = 0;
};

Hashtable(int hash_table_size)
{
    hashtable.clear();
    hashtable_size = hash_table_size;
    intialize_hashtable();

    //counts the number of elements added into the hashtable
    count_elements_added = 0;

    //counts the number of elements removed from the hashtable
    count_elements_removed = 0;

    //counts the number of elements present in the hashtable
    count_elements_present = 0;
};

//add elemnet to the hashtable
void add_element(int key,int object_identifier,int object_info);

//given the key and the object identifier
//returns the object info
int get_element(int key,int object_identifier);

//delete the element from the hashtable
void remove_element(int key,int object_identifier);

//prints the contents of the hashtable
void print();

void clear_memory()
{
    std::cout<<"clearing hashtable"<<std::endl;
    hashtable.clear();
    hashtable_size = 0;
}

~Hashtable()
{
    hashtable_size = 0;
    hashtable.clear();

    //counts the number of elements added into the hashtable
    count_elements_added = 0;

    //counts the number of elements removed from the hashtable
    count_elements_removed = 0;

    //counts the number of elements present in the hashtable
    count_elements_present = 0;

};
 };

 //initialize the hashtable
 inline void Hashtable :: intialize_hashtable() 
 {
for(unsigned int i = 0;i < hashtable_size;i++)
{
    std :: vector<std :: pair<int,int> > temp;
    temp.clear();
    hashtable.push_back(temp);
}
}

//add elemnet to the hashtable
inline void Hashtable :: add_element(int key,int object_identifier,int object_info)
{   
hashtable[key].push_back(std :: pair<int,int> (object_identifier,object_info));

count_elements_added++;
count_elements_present++;

}

//given the key and the object identifier
//returns the object info
//if the object has not been found then returns the macro : value
inline int Hashtable :: get_element(int key,int object_identifier)
{
//get elements from the hastable that have the same key 
std :: vector<std :: pair<int,int> > same_key_elements = hashtable[key];

//if the hastable array is empty then return not found
if(same_key_elements.empty())
{
    return(NOT_FOUND_IN_HASHTABLE);
}

//scan thru all the elemenets in the hashtable to find if the element is present 
for(std :: vector<std :: pair<int,int> > :: iterator same_key_elements_iter = same_key_elements.begin();same_key_elements_iter != same_key_elements.end();same_key_elements_iter++) 
{
    //check if the object identifier is present in the array
    if((*same_key_elements_iter).first == object_identifier)
    {
        //returns the object info corresponding to the object identifier    
        return((*same_key_elements_iter).second);
    }
}

same_key_elements.clear();


//if the element has not been found then return the default value
return(NOT_FOUND_IN_HASHTABLE);
 }

 //given an key and the element object_identifier,removes the element from the hashtable
 inline void Hashtable :: remove_element(int key,int object_identifier)
 {  
//get elements from the hastable that have the same key 
std :: vector<std :: pair<int,int> > same_key_elements = hashtable[key];

//saves the remanining elements in the array after the element woth the same key has been found
std :: vector<std :: pair<int,int> > remaining_key_elements;
remaining_key_elements.clear();

//if the hastable array is empty then no deletion can take place
if(same_key_elements.empty())
{
    return;
}

//scan thru all the elemenets in the hashtable to find if the element is present 
for(std :: vector<std :: pair<int,int> > :: iterator same_key_elements_iter = same_key_elements.begin();same_key_elements_iter != same_key_elements.end();same_key_elements_iter++) 
{
    //check if the object identifier is not present in the array
    if(!((*same_key_elements_iter).first == object_identifier))
    {
        remaining_key_elements.push_back(std :: pair<int,int> ((*same_key_elements_iter).first ,(*same_key_elements_iter).second));
    }
}

hashtable[key] = remaining_key_elements;
same_key_elements.clear();
remaining_key_elements.clear();

//update the hashtable counts
count_elements_removed++;
count_elements_present--;

}

//checks whether the hashtable is corrupted or not
//returns true,if the hashtable is corrupted
//else returns false
inline bool Hashtable :: is_corrupt()
{
 //the size of the hashtable should be equal to the size it was initialised
if(hashtable.size() != hashtable_size)
 {
    return(true);
 }
//the number of elements added - no. of elements removed should be equal to the no. of elements present in the hashtable
 else if((count_elements_added -count_elements_removed) != count_elements_present) 
 {
     return(true);
 }
 //default case :
 else
{
    return(false);
 }
 }

//prints the contents of the hashtable
inline void Hashtable :: print()
{
 //checks the case where the hashtable may be empty
 if(hashtable.empty())
 {
    std :: cout<<"the hash table is empty"<<std :: endl;
 }

  //printing the contents of the hashtable
  unsigned int pos = 0;
for(std :: vector< std :: vector<std :: pair<int,int> > > :: iterator  hashtable_iter = hashtable.begin();hashtable_iter != hashtable.end();hashtable_iter++,pos++)
 {
     std :: cout<<"key = "<<pos;
    std :: vector<std ::pair<int,int> > tmp =  *hashtable_iter;
     //Tools :: print(tmp);  
     std :: cout<<std :: endl;
}
 }

 #endif

分段错误即将到来。代码的输出是:

 gng of scope
 clearing child
 clearing parent
 clearing dummy
 comple
 Segmentation fault (core dumped)

请指导如何调试此问题。我尝试了 gdb,但我不明白分段错误的原因。

【问题讨论】:

  • 您需要关注rule of three
  • 你应该初始化所有的指针,这样你就可以在它们上面调用delete。要么让它们指向一个动态分配的对象,要么将它们设置为nullptr,(或0NULL,如果C++11 之前的版本。)

标签: c++ pointers vector gdb segmentation-fault


【解决方案1】:

Parent 中的delete(nodes_hashtable);,我认为您没有为nodes_hashtable 分配内存。

请使用

parent()
{
    nodes_hashtable=NULL;
    p = new dummy();
}
virtual ~parent()
{
    cout<<"clearing parent"<<endl;
    delete(p);
    if(nodes_hashtable)
        delete(nodes_hashtable);
}

如果没有为nodes_hashtable分配内存,这段代码不会调用delete。

【讨论】:

  • 我认为create_nodes_hashtable 不叫
  • 是的,它没有被调用,在代码块中只创建了子对象,没有其他操作。
  • @JKB 仍然是一个不完整的答案,就像其他人一样。
【解决方案2】:

nodes_hashtable 未初始化,因此该指针可以包含任何数据。你必须在parent构造函数中初始化它:

parent() :
    p(new dummy()),
    nodes_hashtable(NULL)
{}

在进一步的代码中具有可预测的条件。 您也可以在大多数编译器不检查 NULL 的情况下删除 NULL 指针,因此没有重要的理由来更改 parent 析构函数

【讨论】:

    【解决方案3】:
    nodes_hashtable is point to null which would cause core dump to free null memory。
    
    
    class parent
    {
    public:
    dummy *p;
    Hashtable *nodes_hashtable;
    parent()
    {
        p = new dummy();
    nodes_hashtable=NULL;
    }
    
    void create_nodes_hashtable();
    
    virtual ~parent()
    {
        cout<<"clearing parent"<<endl;
        delete(p);
        if(nodes_hashtable != NULL)
            delete(nodes_hashtable);
    }
    
     };
    
     //given the hashtable,updates the values in the hashtable
     void parent ::  create_nodes_hashtable()
    {
    if(nodes_hashtable  == NULL)
        nodes_hashtable = new(std::nothrow) Hashtable(500);
    else 
        return;
    
    //check :if the hashtable has been created
    if(NULL == nodes_hashtable)
    {
        cout<<"out of memory"<<endl;
    }
    
    for(unsigned int i = 0;i<20 ;i++)
    {       
        //normalising the key ,so that the key lies within the range of the hashtable
        int key = i;//get_nodes_hashtablekey(i,i);
        (*nodes_hashtable).add_element(key,i,i);
    }
    } 
    

    【讨论】:

    • 代码仍然严重损坏。这只是解决了一个特定问题。如果 parent 被构造或分配了副本,它就会爆炸。
    • 如果代码正常,则代码不会被破坏。也就是说,三法则是一个非常的好主意,可以防止你在脚上开枪。
    • 浅拷贝问题可以通过覆盖拷贝构造函数和运算符=,或者智能指针来解决。或者将类定义为单例
    猜你喜欢
    • 1970-01-01
    • 2011-10-22
    • 2021-09-24
    • 2021-11-28
    • 2021-12-21
    • 1970-01-01
    • 2021-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多