У меня есть очень простая фиктивная программа
levenshteindb.h:
#ifndef LEVENSHTEINDB_H
#define LEVENSHTEINDB_H
#include <QVector>
#include "levenshteindbnode.h"
class LevenshteinDB
{
unsigned size;
QVector<LevenshteinDBNode> nodes;
void realloc_rows(unsigned node);
public:
LevenshteinDB();
~LevenshteinDB();
void add_word();
};
#endif // LEVENSHTEINDB_H
levenshteindb.cpp:
#include "levenshteindb.h"#include <cstring>
#include <cstdio>
LevenshteinDB::LevenshteinDB()
{
size=15;
nodes.append(LevenshteinDBNode(size));
}
LevenshteinDB::~LevenshteinDB()
{
}void LevenshteinDB::add_word()
{
nodes.append(LevenshteinDBNode(size));
}void LevenshteinDB::realloc_rows(unsigned newsize)
{
for(unsigned i=0;i<nodes.size();i++)
nodes[i].realloc(newsize);
}
levenshteindbnode.h:
#ifndef LEVENSHTEINDBNODE_H
#define LEVENSHTEINDBNODE_H
struct LevenshteinDBNode
{
LevenshteinDBNode();
LevenshteinDBNode(unsigned size);
~LevenshteinDBNode();
unsigned *row;
void realloc(unsigned newsize);
};
#endif // LEVENSHTEINDBNODE_H
levenshteindbnode.cpp:
#include "levenshteindbnode.h"
LevenshteinDBNode::LevenshteinDBNode(){};
LevenshteinDBNode::LevenshteinDBNode(unsigned size)
{
row = new unsigned[size];
}
LevenshteinDBNode::~LevenshteinDBNode()
{
delete[] row;
}
void LevenshteinDBNode::realloc(unsigned newsize)
{
delete[] row;
row=new unsigned[newsize];
}
main.cpp:
#include "levenshteindb.h"
int main()
{
LevenshteinDB *trie = new LevenshteinDB();
trie->add_word();
trie->add_word();
trie->add_word();
delete trie;
}
это дает сбой и, кажется, имеет огромную (по сравнению с памятью, выделенной самой программой) утечку памяти, но я действительно не могу понять, что не так ..
Я использую QT 5.2
Вам нужно прочитать о правило трех.
Что происходит, когда вы делаете
nodes.append(LevenshteinDBNode(size));
Вы создаете временный LevenshteinDBNode
объект, который затем скопированный, приводя к двум объектам с двумя указателями на одну и ту же память. Временный объект затем уничтожается, что вызывает ваш деструктор и удаляет выделенную вами память. Теперь у вас есть копия объекта с указателем на удаленную память.
Вам необходимо реализовать конструктор копирования который делает так называемую глубокую копию выделенной памяти.
У вас также есть гораздо более тонкая ошибка в вашем коде, потому что вы не инициализируете указатель в LevenshteinDBNode
конструктор по умолчанию. Это означает, что если у вас есть экземпляр, созданный по умолчанию, указатель будет иметь неопределенное значение, в действительности он будет указывать на случайное местоположение. Это приведет к неопределенному поведению, если созданный по умолчанию экземпляр будет уничтожен при попытке delete
этот случайный указатель. Вам нужно инициализировать указатель на nullptr
в конструкторе по умолчанию.
Других решений пока нет …