1

I´m currently playing around with linked lists today. I got everything to work just fine though I always seem to run into the same Problem,the destructor no matter what, it seems to always run into a NULL object when accessing the destructor in any form, throwing an "access rights violation Error"

"this->next" was "0xDDDDDDDD".

struct Liste {
Liste *next;
int content;
Liste() {
    content = 0;
    next = nullptr;
};
~Liste() {
    if (next == nullptr) {
        return;
    }else if (next->next == nullptr){
        delete next;
        return;
    }else {
        next->~Liste();
    }
};
};

I´m quite unsure and curious about what could be the source for this Error. It always occurs no matter the way i try to use delete on it. The solutions i found so far were: -simply call delete on the first element and it calls the destructor of the others -try to check if next in line IS Null but it doesn´t seem to filter it out at all -try to go through it iteratively but that too did run into ground zero -try to implement it in a class which did work just as fine as this did, up to the point i had to implement a deletion which ran into the exact same Error

Id be happy to receive some tips on how to fix/avoid this since not deleting it at all cant be a good idea, and i'm not sure at all what exactly went wrong in the code.

Cœur
  • 37,241
  • 25
  • 195
  • 267
  • 1
    Welcome to Stack Overflow. Please take the time to go through the [The Tour](http://stackoverflow.com/tour) and refer to the material from the [Help Center](http://stackoverflow.com/help/asking) on what and how you can ask here.It's specially important to post a [mcve]. – R Sahu Aug 14 '18 at 17:21
  • 2
    According to [Wikipedia's great list of magic debug codes](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_debug_values), 0xDDDDDDDD suggests access of memory that has already been freed. Know ye [The Rule of Three!](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) – user4581301 Aug 14 '18 at 17:29
  • 4
    Unrelated `next->~Liste();` is a bad idea. You almost never want to manually call a destructor (Notable exceptions are non-POD union members and objects constructed with placement new). Use `delete next;` instead. – user4581301 Aug 14 '18 at 17:35
  • You have a memory leak in your program due to manually calling destructor, but that unlikely be the roor cause of that memory access. we cannot help you without [mcve]. – Slava Aug 14 '18 at 17:43
  • 1
    Possible duplicate of [What is The Rule of Three?](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) – Alan Birtles Aug 14 '18 at 18:02

2 Answers2

1

Your destructor just needs to do:

~Liste() {
    delete next;
}

If next is not null, then delete next; will call the destructor of the next element, which in turn will call the destructor of the next element, and so on. If next is null then delete next; will not do anything, which is fine.

jdehesa
  • 58,456
  • 7
  • 77
  • 121
  • 6
    This is a recipe for overflowing your stack. You recurse up to a depth of `n` – Justin Aug 14 '18 at 17:22
  • @Justin Yes, you're right about that, I was thinking of a "programming practice" solution but in a real use case an iterative solution would be better, feel free to post one and I'll upvote that. – jdehesa Aug 14 '18 at 17:24
  • And how does this explain what is wrong with and point to the error in the OP's code? – Matthias Aug 14 '18 at 17:27
  • 1
    Calling `delete` on null pointers is not what it used to be. https://stackoverflow.com/questions/25329576/calling-delete-on-null-pointers-c03-vs-c11. – R Sahu Aug 14 '18 at 17:27
  • @Justin I don't think a stack overflow should be a concern in simple code like this. At worst, every stack frame need only hold a single `this` pointer and you'd need an enormous list to cause problems. This destructor could also easily be optimized into a loop for being essentially tail-recursive. – alter_igel Aug 14 '18 at 17:32
  • 1
    @alterigel Perhaps, but also consider that running in debug with no optimizations on is a very common occurrence. As a rule of thumb, only recurse if you can keep the stack growth as `O(log n)` – Justin Aug 14 '18 at 17:34
  • 1
    I wish C++ had tail recursion optimization. :-( – Eljay Aug 14 '18 at 17:44
  • This is not an answer for the question, though that destructor is written badly, it is unlikely it is the reason for that memory access – Slava Aug 14 '18 at 17:45
  • 4
    @Eljay I'm waiting for the telepathic compiler. One that generates code that does what you want, not what you told it to. – user4581301 Aug 14 '18 at 20:19
1

Without a stack overflow compared to the previous answer:

~Liste() {
     Liste* temp = nullptr;
     while (next) {
         temp       = next->next;
         next->next = nullptr;
         delete next;
         next       = temp;
     }
 }

With regard to the given code:

~Liste() {
    if (next == nullptr) {
        return;
    } else if (next->next == nullptr){
        delete next;
        return;
    } else {
        next->~Liste(); // *next is destructed, but next is not deallocated!
    }
};

Though, the given code (including the destructor) is probably not the reason for the bad memory access as already mentioned by Slava.

Matthias
  • 4,481
  • 12
  • 45
  • 84
  • I think proper solution is to have separate classes for node and list itself, and implement this logic in list's destructor. Here list has link to another list, which is actually a node. – Slava Aug 14 '18 at 17:49
  • @Slava indeed; I once wrote a [doubly linked list](https://github.com/matt77hias/cpp-samples/blob/master/Samples/doubly_linked_list/code.hpp) which uses a separate class to represent the links. – Matthias Aug 14 '18 at 17:52
  • I think just about everybody wrote that doubly linked list program at one point or another. God it must get boring to mark this stuff after a while. – user4581301 Aug 14 '18 at 19:43