深拷贝的分割错误

时间:2014-04-16 22:48:21

标签: c++ constructor copy copy-on-write

我正在尝试对对象进行深层复制(用于写入时的复制),但是我遇到了分段错误。

我正在使用带链表的哈希表。

    class Person
{
public:
    Person(const char * id,int nb)
    {
        this->id=strdup(id);
        this->nb=nb;
        this->init=init;
        this->next=NULL;
    }
    Person(const Person& rhs) :
    nb(rhs.nb),
    init(rhs.init),
    id(strdup(rhs.id)),
    next(rhs.next == NULL ? NULL : new Person(*rhs.next)) {}

    char* strdup(char const* in)
    {
        char* ret = new char[strlen(in)+1];
        strcpy(ret, in);
        return ret;
    }

    int nb,init;
    const char * id;
    Person *next;
};


    Hashtable deepcopy (const Hashtable& rhs)
    {
    num[0]=num[0]-1;
    Person** array=rhs.table;
    Hashtable autre;
    for (int i = 0 ; i < size; ++i)
        if (autre.table[i]!=NULL)
            autre.table[i] = new Person(*array[i]);
    return autre;
    num[0]=1;
}

我班Hashtable的归属:

 Person **table;
    int* num;

编辑:此问题似乎已修复。 我的深拷贝有什么问题?我不明白。我认为我的拷贝构造函数很好,但我不明白为什么在运行它时会出现seg错误。

2 个答案:

答案 0 :(得分:1)

此代码必须修复:

for (int i = 0 ; i < size; ++i)
    autre.table[i] = new Person(*array[i]);

table具有固定大小,并且填充了空指针。在循环中,您不检查要复制的元素是否为空指针,因此您要对其进行反驳并尝试复制甚至不存在的实体。

for (int i = 0 ; i < size; ++i) {
    if(array[i] != NULL) {
        autre.table[i] = new Person(*array[i]);
    }
}

PS:最好使用nullptr代替NULL

答案 1 :(得分:0)

我看到的问题:

  1. Person的默认构造函数。

    Person(const char * id,int nb)
    {
      this->id=id;
      this->next=NULL;
    }
    

    如果我使用

    Person foo()
    {
      char id[] = "John";
      return Person(id, 0);
    }
    
    Person a = foo();
    

    然后堆栈存储器用于保存&#34; John&#34; foo中的a现在由std::string保留,这将导致未定义的行为。

    您需要获取输入字符串的所有权。使用id代替char const*

  2. 复制Person的构造函数。

    声明

    id(rhs.id),
    
    如果您决定将char const*用作id的类型,

    将会出现问题。如果您将其切换为std::string,则不会出现问题。

  3. HashTable的复制构造函数生成table的浅表副本。如果您决定删除table的析构函数中的HashTable,这将是一个问题。如果您未在table的析构函数中删除HashTable,则会导致内存泄漏。

  4. deepcopy中,在解除引用之前,您不会检查array[i]是否为NULL。 @alphashooter已经指出了这一点。此外,您正在函数autre的局部变量中创建深层副本。除非您从中返回autre,否则深层副本在函数外部不可见。

  5. 修改 由于您不允许使用std::string,因此您必须为默认构造函数中的char const*以及复制构造函数分配内存。如果您的平台具有非标准函数strdup并且您可以使用它,则可以将默认构造函数更改为:

    Person(const char * id,int nb)
    {
      this->id=strdup(id);
      this->next=NULL;
    }
    

    您需要对复制构造函数进行类似的更改。

    如果您没有strdup或者您不允许使用它,则可以对其进行定义。这是一个非常简单的写作功能。

    char* strdup(char const* in)
    {
      char* ret = new char[strlen(in)+1];
      strcpy(ret, in);
      return ret;
    }