Memory leaks despite destructor call

2019-09-17 09:43发布

I'm working on a class LinkedList which looks like this:

private:
    LL_element* first;
    LL_element* last; 
    int size;
public:
    //constructor
    Linkedlist(): first(NULL), last(NULL), size(0) {}

    //destructor
    ~Linkedlist();

    //adds element at the end of the list.
    void push_back(int value);

    //removes an element at the end of the list.
    bool pop_back(int& value);

The function push_back creates a new LL_element object (dynamically allocated). The function pop_back explicitly deletes the element at the end of the list. The destructor uses the function pop_back as long as the list is not empty. The problem is that when I create a Linkedlist object:

Linkedlist foo =   Linkedlist();
foo.push_back(3);
foo.push_back(5);

When foo goes out of scope the destructor is called, but Visualstudio still gives me memoryleaks of the LL_elements. However when I dynamically allocate:

Linkedlist* foo = new Linkedlist();
foo->push_back(3);
foo->push_back(5);

And then call the destructor with 'delete', VS does not give memoryleaks.

Is the destructor not properly called by the compiler or is the default constructor not properly used when creating a Linkedlist on the stack? It's really confusing me...

The code for push_back and pop_back:

bool Linkedlist:: pop_back(int& value) {

//only if the list is not empty, an element can be removed.
if(!this->is_empty()) {

    value = this->last->get_value();
    LL_element* removed = this->last;
    this->last = removed->get_previous();

    if(this->size!=1) {
    this->last->set_next(NULL);
    }

    delete removed; 
    size--;
    return true;
}   

value = 0;
cout << EMPTY_LIST_MESSAGE << endl;
return false;}

void Linkedlist:: push_back(int value)
{

LL_element* to_add = new LL_element(value);

//if there already is a first element, we can ignore it
if(!this->is_empty()) {

    this->last->set_next(to_add);
    to_add->set_previous(last);
    this->last = to_add;
    size++;

}

//if the list is empty --> special case.
else {

    this->first = to_add;
    this->last = to_add;
    size++;

}
}

An SSCCE:

int main(int argc, const char * argv[]) {

Linkedlist foo; 
foo.push_back(3);
foo.push_back(5);
foo.push_back(6);
foo.push_back(7); 
_CrtDumpMemoryLeaks();
return 0;
}

Output:

Detected memory leaks!
Dumping objects ->
{139} normal block at 0x00A58148, 12 bytes long.
 Data: <            > 00 00 00 00 00 81 A5 00 07 00 00 00 
{138} normal block at 0x00A58100, 12 bytes long.
 Data: <H           > 48 81 A5 00 B8 80 A5 00 06 00 00 00 
{137} normal block at 0x00A580B8, 12 bytes long.
 Data: <     0      > 00 81 A5 00 F0 30 A5 00 05 00 00 00 
{136} normal block at 0x00A530F0, 12 bytes long.
 Data: <            > B8 80 A5 00 00 00 00 00 03 00 00 00 
Object dump complete.
The program '[5592] linkedlist.exe' has exited with code 0 (0x0).

1条回答
我命由我不由天
2楼-- · 2019-09-17 10:14

You are checking for memory leaks before foo goes out of scope, so it doesn't have a chance to call its destructor which in turn probably clears all LL_elements (assumption, since you haven't posted destructor code). Try it like this:

int main(int argc, const char * argv[]) {
    {
        Linkedlist foo; 
        foo.push_back(3);
        foo.push_back(5);
        foo.push_back(6);
        foo.push_back(7); 
    }
    _CrtDumpMemoryLeaks();
    return 0;
}
查看更多
登录 后发表回答