0

我想为双链表编写一个natvis visualizer。该列表没有存储计数节点,并且简单的方法不能很好地工作,因为展开从不停止(next从不为空,列表的最后一项指向列表根目录)。使用natvis的圆形双链表可视化

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

我希望我将能够添加一个条件属性的NextPointer与表头进行比较,但作为NextPoint公司在节点的上下文中计算的,我不知道该怎么把它与比较:

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

这是怎么与以前的(2010)展示台长得很像,利用跳转指令,为#list was handling this automatically

#list是对无限特拉沃保护并会优雅地处理一份通告。此外,您可以使用skip:表达式来表示不应报告的哨兵节点。尽管名称意味着该节点将被跳过,但实际上会导致遍历停止,所以如果您的哨兵节点是第一个,则应该在它之后开始遍历。

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

我怎样才能在natvis到调试器应该停止扩大名单一旦再次到达根元素解释一下吗?

回答

2

natvis框架目前不支持没有提供计数的循环链表。如果你提供一个计数,它应该工作。然而,没有数据,就没有好办法阻止扩张永远持续下去。

1

我有一个类似的问题,而不是一个循环列表,但在末端指向自己的哨兵节点,并提出了一个有趣的解决方案,可能适合您的需求:您可以使用三元运算符伪造真正的终止。 <NextPointer>中的表达式可以是任何你可以在香草C中写的东西,所以你可以在那里做真正的计算(但可惜,没有递归)。

(请注意,你不能把Condition属性上<NextPointer>,所以三元运算符是实现条件存在的唯一途径)在我的情况

所以,名单终止这样的:

<LinkedListItems> 
    <HeadPointer>this</HeadPointer> 
    <NextPointer>next != this ? next : 0</NextPointer> 
    <ValueNode>items</ValueNode> 
</LinkedListItems> 

在你的情况,如果每个节点都有一个指向其容器,你可以用它来比较对头节点:

<LinkedListItems> 
    <HeadPointer>container-&gt;head</HeadPointer> 
    <NextPointer>next != container-&gt;head ? next : 0</NextPointer> 
    <ValueNode>items</ValueNode> 
</LinkedListItems> 

或者,没有&gt;实体和写为更传统的C,这相当于:

next != container->head ? next : NULL 

如果没有某种container回指针,不过,你可能是出于运气在这,因为没有办法通过查看循环链表中的单个节点来回答它是否实际上是“最后”节点。

+0

嗯,你没有三元向后?它不应该是'next!= container-> head?下一个:0'?或者我可能不了解你在做什么? – Adrian 2016-03-31 23:05:17

+0

是的,它在这个版本中倒退了;我会纠正它。我使用的实际代码要复杂得多,因为数据结构要复杂得多,但是在一些额外的指针间接指针仍然松散地归结为一个循环链表之后。我搞砸了这个帖子的核心逻辑。 – 2016-04-02 23:23:14

+0

我不知道VS2012,但在VS2013中,如果列表最终碰到''中描述的指针,它也会停止列表,就好像''指向nullptr。 – Adrian 2016-04-04 20:14:03

2

您可以用CustomListItems元素做到这一点:

<CustomListItems> 
    <Variable Name="orig_head" InitialValue="head"/> 
    <Variable Name="iter" InitialValue="first_elem"/> 
    <Loop> 
     <Break Condition="iter == orig_head || iter == 0"/> 
     <Item>*iter</Item> 
     <Exec>iter = iter-&gt;next_elem</Exec> 
    </Loop> 
</CustomListItems> 

CustomListItems让你的头保存在一个变量,因此它可以遍历该列表中使用。如果您的头部具有不同的类型,那么您需要将它转换为节点类型。