ошибка сегментации с глубокой копией

Я пытаюсь сделать глубокую копию (для копирования при записи) объекта, но получаю ошибку сегментации.

Я использую хеш-таблицу со связанным списком.

    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;

РЕДАКТИРОВАТЬ: эта проблема, кажется, исправлена.
Что не так с моей глубокой копией? Я не понимаю Я думаю, что мой конструктор копирования хорош, но я не понимаю, почему я получаю ошибку сегмента при запуске.

-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

Другие решения

Проблемы, которые я вижу:

  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();
    

    Затем стек памяти используется для хранения «Джона» в 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 от него.

РЕДАКТИРОВАТЬ
Поскольку вы не можете использовать 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;
}
0

По вопросам рекламы [email protected]