Search code examples
c++visual-studiodebuggingdebuggervisualizernatvis

Circular Double Linked list visualization using natvis


I would like to write a natvis visualizer for a double linked list. The list does not have a count node stored, and the easy way does not work very well, as the expansion never stops (next is never null, the last item of the list is pointing to the list root).

<Type Name="TListBidir&lt;*&gt;">
    <Expand>
        <LinkedListItems>
            <HeadPointer>next</HeadPointer>
            <NextPointer>next</NextPointer>
            <ValueNode>($T1 *)this</ValueNode>
        </LinkedListItems>
    </Expand>
</Type>

I hoped I will be able to add a Condition attribute the the NextPointer comparing it with the list head, but as the NextPoint is evaluated in the context of the node, I do not know what to compare it with:

<NextPointer Condition="next!=XXXXXXXXX">next</NextPointer>

This is how it looked like with previous (2010) visualizers, using the skip directive, as the #list was handling this automatically:

#list is protected against infinite traversals and will cope gracefully with a circular list. Also, you can use a skip: expression to denote a sentinel node that should not be reported. Although the name implies that the node will be skipped, it actually causes traversal to stop, so if your sentinel node is first you should start traversal after it.

TListBidir<*,*,*>{
    children
    (
      #list(
        head: ((($T2 *)&$c)->next),
        next: next,
        skip : &($c)
      ): (($T1 *)(&$e))
    )
}

How can I explain in the natvis to the debugger it should stop expanding the list once it reaches the root element again?


Solution

  • The natvis framework does not currently support circular linked lists without a count provided. If you provide a count, it should work. However, without a count, there is no good way to prevent the expansion from just continuing on forever.