1

我想为双链表编写一个natvis 可视化工具。该列表没有存储计数节点,并且简单的方法效果不佳,因为扩展永远不会停止(next 永远不会为空,列表的最后一项指向列表根)。

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

我希望我能够添加一个 Condition 属性,将 NextPointer 与列表头进行比较,但是由于 NextPoint 在节点的上下文中进行评估,我不知道将其与什么进行比较:

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

这是使用 skip 指令的以前(2010)可视化工具的样子,因为#list 会自动处理

#list可以防止无限遍历,并且可以优雅地处理循环列表。此外,您可以使用skip:表达式来表示不应报告的哨点节点。虽然名字暗示该节点将被跳过,但它实际上会导致遍历停止,所以如果你的哨兵节点是第一个,你应该在它之后开始遍历。

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

我如何在 natvis 中向调试器解释它一旦再次到达根元素就应该停止扩展列表?

4

3 回答 3

3

我有一个类似的问题,不是循环列表,而是在末尾有一个指向自身的哨兵节点,并提出了一个可能适合您需求的有趣解决方案:您可以使用三元运算符伪造一个真正的终止。里面的表达式<NextPointer>可以是任何你可以用 vanilla 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反向指针,那么您可能对此不走运,因为无法通过仅查看循环链接列表中的单个节点来回答它是否实际上是“最后一个“节点。

于 2016-03-09T15:04:09.933 回答
3

你可以用一个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允许您将头部保存在变量中,以便在遍历列表时使用它。如果您的头部具有不同的类型,那么您需要将列表节点转换为节点类型。

于 2016-08-22T16:20:40.383 回答
2

natvis 框架目前不支持没有提供计数的循环链表。如果您提供计数,它应该可以工作。但是,如果没有计数,就没有好的方法可以阻止扩张永远持续下去。

于 2012-08-15T20:09:19.907 回答