Hacker News new | ask | show | jobs
by Arnavion 3688 days ago
The `tmp != head` comparion is UB because `head` is a dangling pointer after the first loop iteration, right?
2 comments

Yep! To do this properly requires something more like:

    void free_circularly_linked_list(struct node *head) {
      struct node *tmp = head->next;
      while (1) {
        if (tmp == head) {
          /* Has to be a separate case since even assigning
           * a dangling pointer is UB I believe? */
          free(tmp);
          break;
        } else {
          struct node *next = tmp->next;
          free(tmp);
          tmp = next;
        }
      }
    }
I'm not sure what you are trying to achieve by using the infinite loop. There's a more direct way.

    void free_circularly_linked_list(struct node *head)
    {
      struct node *a = head->next;
      while (a != head) {
        struct node *b = a->next;
        free(a);
        a = b;
      }
      free(head);
    }
Great example, by the way!
Why is it UB?

Let's say head value is "10" and the memory at "10" is {..., next: "10"}

After the first iteration we will have:

Head: "10" Next: "10" Temp: "10"

With "10" pointing to freed memory. But why do we care? We are not dereferencing it, are we?

(I think I am missing something very obvious)

I think you’re missing the fact that "There are a lot of rules you need to be aware of that are not naturally-occurring results of the fundamentals."
I was indeed. Thanks for the insight!
Because the standard says even comparing a dangling pointer is UB, which was haberman's point about the standard being non-intuitive.
Thanks. I wasn't aware of that. I stand corrected!!