Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Your problem is that you're initializing rear->link to tmp in your enqueue function - change the line <code>rear-&gt;link = tmp</code> to <code>rear-&gt;link = NULL</code> in the empty-queue part of <code>enqueue()</code> and it works fine for me ^^ your last node shouldn't point to anything, you're trying to delete the same memory twice when you get to the end because that memory is linked to itself.</p> <p>EDIT: And now for the far more important answer. Both your list and your queue implementations don't follow the <a href="https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three">Rule of Big Three</a>. A basic rundown of the rule is this (though you should DEFINITELY still read the link - it's one of the most important idioms in C++):</p> <p><strong>If a class manages a resource dynamically, it should provide a copy constructor, assignment operator AND a destructor.</strong> Any class that breaks this rule (ie. yours) run the risk of creating copies of pointers, then deleting them. In your example, what it looks like is this:</p> <p>Your queue is initialized with the string you expected. Everything looks fine. Then you call the function <code>l.insert(queue, 0)</code>, which is prototyped as follows: <code>int insert(queue c, int position);</code></p> <p>The important thing to notice is that the queue is passed by VALUE, meaning that a COPY of it gets made (using the <strong>copy constructor</strong> - rule of big three #1), then the list node gets created with the data of THAT COPY - meaning the head pointer, most specifically. Since you didn't provide a copy constructor, that pointer just gets copied bitwise - meaning the copy of your queue (the data of which you're inserting into the list) has the EXACT SAME head pointer as the queue you passed in, but it's a different object.</p> <p>Then, you write the line <code>tmp-&gt;data=c;</code> - which is another one of your Big Three functions, the <strong>assignment operator</strong>. Again, you don't provide one - so that pointer is assigned bitwise again, leading to the same problem as with the copy constructor.</p> <p>So far we've got three copies of our queue object we passed in, all of them with the same head pointer. See where we're going yet?</p> <p>Now, when your <code>list::insert()</code> function finishes up, it destroys all the local objects it created. What does that mean? It means calling the destructor of the copy you created when you passed the queue by value. Since it has the same head pointer as the other two copies of that queue you have, it goes through their lists as well as its own, deleting everything willy-nilly. So now, your list node's queue's data is garbage, but we haven't quite crashed and burned fully yet. Let's see what happens when your program exits.</p> <p>Now the fun starts - the double-free error you were seeing (in fact, it's a triple free, since we made three copies, remember?). As your program exits, both of the other copies' destructors are called as well - and they try to go through the list, deleting everything again.</p> <p><strong>So, how do we solve these problems?</strong></p> <p>The link provided will give you a more in-depth explanation - but what you need to do is ensure those classes both provide ALL of the functions in the rule of big three, and that those functions make a <a href="https://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy">deep copy</a> wherever necessary - instead of copying the pointer to the head (for example), your queue should create a <code>new qnode;</code>, set that as its head, and fill its data with a copy of the other list's head's data. For example (and I didn't compile this, and there's no error checking, and etcetera) your copy constructor for queue could look like this:</p> <pre><code>Queue::Queue(const Queue &amp;other) { head = new qnode; //IMPORTANT: don't copy the value of the pointer (like the compiler // will by default if you let it) head-&gt;data = other.head-&gt;data; qnode *tmp = other.head-&gt;link; while (tmp != nullptr) { qnode *tmp2 = new qnode; //again, don't copy the value of the pointer! tmp2-&gt;data = tmp.data; //make a new node and copy the data tmp2-&gt;link = nullptr; rear-&gt;link = tmp2; //update the tail of the list rear = tmp2; } } </code></pre> <p>Hope that helps... it was more typing than I expected! but you gave a REALLY good example of why the Rule of Big Three is one of the most important idioms in C++. These things will happen EVERY TIME you break the Rule of Big Three.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload