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讓你的頭保存在一個變量,因此它可以遍歷該列表中使用。如果您的頭部具有不同的類型,那麼您需要將它轉換爲節點類型。