Question

I have this very simple dummy program

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;
}

that crashes and seems to have a huge (compared to the memory allocated by the program itself) memory leak, but I really cannot understand what's wrong.. I'm using qt 5.2

Was it helpful?

Solution

You need to read about the rule of three.

What's happening is that when you do

nodes.append(LevenshteinDBNode(size));

you create a temporary LevenshteinDBNode objectm which is then copied, leading to two objects with two pointers to the same memory. The temporary object is then destroyed which causes your destructor to be called, and which deletes the memory you've allocated. Now you have a copy of the object, with a pointer to the deleted memory.

You need to implement a copy constructor which does a so called deep copy of the memory allocated.


You also have a much more subtle error in your code, in that you don't initialize the pointer in the LevenshteinDBNode default constructor. This means that if you have a default-constructed instance, the pointer will have an indeterminate value, in reality it will point to a random location. This will lead to undefined behavior if a default-constructed instance is then destructed when you try to delete this random pointer. You need to initialize the pointer to nullptr in the default constructor.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top