• 《Debug UE4/3 FString》


    UE3或者UE4的FString类型无法在内存中直接看到值,为了debug方便,需要第三方文件的协助,可以将以下两个文件UE3.natvis和UE4.natvis拷贝到$USERPROFILE/Documents/Visual Studio 2012/Visualizers 目录下,在debug的时候可以实时看到FString的值了:

    <?xml version="1.0" encoding="utf-8"?>
    <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
    
      <!-- Epic Games, Inc. UE3 Visualizers -->
      <!-- Copy this into c:Users<Your user folder>My DocumentsVisual Studio 2012Visualizers -->
    
      <!-- FString visualizer -->
      <Type Name="UE3::FString">
        <DisplayString Condition="ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &lt; ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &gt;= ArrayNum">{AllocatorInstance.Data,su}</DisplayString>
        <StringView Condition="ArrayMax &gt;= ArrayNum">AllocatorInstance.Data,su</StringView>
      </Type>
    
      <!-- FName visualizer -->
      <Type Name="UE3::FName">
        <DisplayString Condition="Index &gt;= Names.ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="Index &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="0 == (((((FNameEntry**) Names.AllocatorInstance.Data)[Index])->Index) &amp; 1) &amp;&amp; Number &gt; 0">{(((FNameEntry**) Names.AllocatorInstance.Data)[Index])->AnsiName,s}_{Number - 1}</DisplayString>
        <DisplayString Condition="1 == (((((FNameEntry**) Names.AllocatorInstance.Data)[Index])->Index) &amp; 1) &amp;&amp; Number &gt; 0">{(((FNameEntry**) Names.AllocatorInstance.Data)[Index])->UniName,su}_{Number - 1}</DisplayString>
        <DisplayString Condition="0 == (((((FNameEntry**) Names.AllocatorInstance.Data)[Index])->Index) &amp; 1)">{(((FNameEntry**) Names.AllocatorInstance.Data)[Index])->AnsiName,s}</DisplayString>
        <DisplayString Condition="1 == (((((FNameEntry**) Names.AllocatorInstance.Data)[Index])->Index) &amp; 1)">{(((FNameEntry**) Names.AllocatorInstance.Data)[Index])->UniName,su}</DisplayString>
      </Type>
    
      <!-- TArray visualizer -->
      <Type Name="UE3::TArray&lt;*,*&gt;|UE3::TArrayNoInit&lt;*,*&gt;">
        <DisplayString Condition="ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &lt; ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &gt;= ArrayNum">Num={ArrayNum}</DisplayString>
        <Expand>
          <ArrayItems Condition="ArrayNum &lt;= ArrayMax">
            <Size>ArrayNum</Size>
            <ValuePointer>($T1*) AllocatorInstance.Data</ValuePointer>
          </ArrayItems>
        </Expand>
      </Type>
    
      <!-- TIndirectArray visualizer -->
      <Type Name="UE3::TIndirectArray&lt;*,*&gt;">
        <DisplayString Condition="ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &lt; ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &gt;= ArrayNum">Num={ArrayNum}</DisplayString>
        <Expand>
          <IndexListItems Condition="ArrayNum &lt;= ArrayMax">
            <Size>ArrayNum</Size>
            <ValueNode>*(($T1**)AllocatorInstance.Data)[$i]</ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
      <!-- TSparseArray visualizer -->
      <Type Name="UE3::TSparseArray&lt;*,*&gt;|UE3::TSparseArrayNoInit&lt;*,*&gt;">
        <DisplayString Condition="Data.ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="Data.ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="Data.ArrayMax &lt; Data.ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="Data.ArrayMax &gt;= Data.ArrayNum">Num={Data.ArrayNum}</DisplayString>
        <Expand>
          <ArrayItems Condition="Data.ArrayNum &lt;= Data.ArrayMax">
            <Size>Data.ArrayNum</Size>
            <ValuePointer>($T1*) Data.AllocatorInstance.Data</ValuePointer>
          </ArrayItems>
        </Expand>
      </Type>
    
      <!-- TMapBase::FPair visualizer -->
      <Type Name="UE3::TMapBase&lt;*,*,*,*,*&gt;::FPair">
          <DisplayString>({Key}, {Value})</DisplayString>
      </Type>
    
      <!-- TMapBase visualizer -->
      <Type Name="UE3::TMapBase&lt;*,*,*,*,*&gt;">
        <DisplayString Condition="Pairs.Elements.Data.ArrayNum &lt;= 0">Empty</DisplayString>
        <DisplayString Condition="Pairs.Elements.Data.ArrayNum &lt;= Pairs.Elements.Data.ArrayMax">Num={Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices}</DisplayString>
        <Expand>
          <IndexListItems Condition="Pairs.Elements.Data.ArrayNum &gt; 0 &amp;&amp; Pairs.Elements.Data.ArrayNum &lt;= Pairs.Elements.Data.ArrayMax">
            <Size>Pairs.Elements.Data.ArrayNum</Size>
            <ValueNode>((TSet&lt;TMapBase&lt;$T1,$T2,$T3,$T4&gt;::FPair,TMapBase&lt;$T1,$T2,$T3,$T4&gt;::KeyFuncs,$T4&gt;::FElement *) Pairs.Elements.Data.AllocatorInstance.Data + $i)-&gt;Value</ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
      <!-- GFx GAtomicValueBase visualizer -->
      <Type Name="GAtomicValueBase">
        <DisplayString>{Value}</DisplayString>
      </Type>
    
      <!-- UObject visualizer -->
      <Type Name="UE3::UObject">
        <DisplayString Condition="Outer">(Name={Name}, Outer={Outer})</DisplayString>
        <DisplayString Condition="!Outer">(Name={Name})</DisplayString>
      </Type>
    
    </AutoVisualizer>
    UE3.natvis
    <?xml version="1.0" encoding="utf-8"?>
    <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
    
      <!-- Epic Games, Inc. UE4 Visualizers -->
      <!-- Copy this into c:Users<Your user folder>My DocumentsVisual Studio 2012Visualizers -->
    
      <!-- FString visualizer -->
      <Type Name="FString">
        <DisplayString Condition="Data.ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="Data.ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="Data.ArrayMax &lt; Data.ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="Data.ArrayMax &gt;= Data.ArrayNum">{Data.AllocatorInstance.Data,su}</DisplayString>
        <StringView Condition="Data.ArrayMax &gt;= Data.ArrayNum">Data.AllocatorInstance.Data,su</StringView>
      </Type>
    
      <!-- FName visualizer -->
      <Type Name="FName">
        <DisplayString Condition="ComparisonIndex &gt;= 2097152">Invalid</DisplayString>
        <DisplayString Condition="ComparisonIndex &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="ComparisonIndex &lt; 2097152 &amp;&amp; Number &gt; 0">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[ComparisonIndex / 16384][ComparisonIndex % 16384]))->AnsiName,s}_{Number-1}</DisplayString>
        <DisplayString Condition="ComparisonIndex &lt; 2097152">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[ComparisonIndex / 16384][ComparisonIndex % 16384]))->AnsiName,s}</DisplayString>
        <StringView Condition="ComparisonIndex &lt; 2097152">((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[ComparisonIndex / 16384][ComparisonIndex % 16384]))->AnsiName</StringView>
      </Type>
      <Type Name="FName">
        <DisplayString Condition="DisplayIndex &gt;= 2097152">Invalid</DisplayString>
        <DisplayString Condition="DisplayIndex &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="DisplayIndex &lt; 2097152 &amp;&amp; Number &gt; 0">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[DisplayIndex / 16384][DisplayIndex % 16384]))->AnsiName,s}_{Number-1}</DisplayString>
        <DisplayString Condition="DisplayIndex &lt; 2097152">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[DisplayIndex / 16384][DisplayIndex % 16384]))->AnsiName,s}</DisplayString>
        <StringView Condition="DisplayIndex &lt; 2097152">((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[DisplayIndex / 16384][DisplayIndex % 16384]))->AnsiName</StringView>
      </Type>
    
      <Type Name="FMinimalName">
        <DisplayString Condition="Index &gt;= 2097152">Invalid</DisplayString>
        <DisplayString Condition="Index &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="Index &lt; 2097152 &amp;&amp; Number &gt; 0">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[Index / 16384][Index % 16384]))->AnsiName}_{Number-1}</DisplayString>
        <DisplayString Condition="Index &lt; 2097152">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[Index / 16384][Index % 16384]))->AnsiName}</DisplayString>
        <StringView Condition="Index &lt; 2097152">((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[Index / 16384][Index % 16384]))->AnsiName</StringView>
      </Type>
    
      <!-- FStatMessage visualizer @see Stats2.h -->
      <Type Name="FStatMessage">
        <!--ST_None=1-->
        <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&amp;0x7) == 1" >{{NoneType NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString>
        <!--ST_int64=2-->
        <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&amp;0x7) == 2" >{{Int64={DebugStatData.Cycles},C={DebugStatData.CCAndDuration[0]},D={DebugStatData.CCAndDuration[1]} NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString>
        <!--ST_double=3-->
        <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&amp;0x7) == 3" >{{Float={DebugStatData.Float} NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString>
        <!--ST_FName=4-->
        <!--ST_Ptr=5-->
        <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&amp;0x7) == 5" >{{Ptr={DebugStatData.Ptr} NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString>
      </Type>
    
      <Type Name="FVector_NetQuantize">
        <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString>
      </Type>
    
      <Type Name="FVector_NetQuantize10">
        <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString>
      </Type>
    
      <Type Name="FVector_NetQuantize100">
        <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString>
      </Type>
    
      <Type Name="FVector_NetQuantizeNormal">
        <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString>
      </Type>
    
      <!-- TEnumAsByte visualizer -->
      <Type Name="TEnumAsByte&lt;*&gt;">
        <DisplayString>{($T1)Value}</DisplayString>
      </Type>
    
      <!-- UObjectBase visualizer -->
      <Type Name="UObjectBase">
        <DisplayString Condition="Outer">(Name={Name}, Outer={Outer})</DisplayString>
        <DisplayString Condition="!Outer">(Name={Name})</DisplayString>
      </Type>
    
      <!-- TArray<*,TFixedAllocator<*> > visualizer -->
      <Type Name="TArray&lt;*,TFixedAllocator&lt;*&gt;&gt;">
        <DisplayString Condition="ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &lt; ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &gt;= ArrayNum">Num={ArrayNum}</DisplayString>
        <Expand>
          <ArrayItems Condition="ArrayNum &lt;= ArrayMax">
            <Size>ArrayNum</Size>
            <ValuePointer>($T1*)AllocatorInstance.InlineData</ValuePointer>
          </ArrayItems>
        </Expand>
      </Type>
    
      <!-- TArray<*,TInlineAllocator<*,*> > visualizer -->
      <Type Name="TArray&lt;*,TInlineAllocator&lt;*,*&gt;&gt;">
        <DisplayString Condition="ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &lt; ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &gt;= ArrayNum">Num={ArrayNum}</DisplayString>
        <Expand>
          <ArrayItems Condition="ArrayNum &lt;= ArrayMax">
            <Size>ArrayNum</Size>
            <ValuePointer Condition="AllocatorInstance.SecondaryData.Data == 0">($T1*)AllocatorInstance.InlineData</ValuePointer>
            <ValuePointer Condition="AllocatorInstance.SecondaryData.Data != 0">($T1*)AllocatorInstance.SecondaryData.Data</ValuePointer>
          </ArrayItems>
        </Expand>
      </Type>
    
      <!-- TArray visualizer -->
      <Type Name="TArray&lt;*,*&gt;">
        <DisplayString Condition="ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &lt; ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &gt;= ArrayNum">Num={ArrayNum}</DisplayString>
        <Expand>
          <ArrayItems Condition="ArrayNum &lt;= ArrayMax">
            <Size>ArrayNum</Size>
            <ValuePointer>($T1*)AllocatorInstance.Data</ValuePointer>
          </ArrayItems>
        </Expand>
      </Type>
    
      <!-- TIndirectArray visualizer -->
      <Type Name="TIndirectArray&lt;*,*&gt;">
        <DisplayString Condition="Array.ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="Array.ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="Array.ArrayMax &lt; Array.ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="Array.ArrayMax &gt;= Array.ArrayNum">Num={Array.ArrayNum}</DisplayString>
        <Expand>
          <IndexListItems Condition="Array.ArrayNum &lt;= Array.ArrayMax">
            <Size>Array.ArrayNum</Size>
            <ValueNode>*(($T1**)Array.AllocatorInstance.Data)[$i]</ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
      <!-- TChunkedArray visualizer -->
      <Type Name="TChunkedArray&lt;*,*&gt;">
        <DisplayString Condition="NumElements == 0">Empty</DisplayString>
        <DisplayString Condition="NumElements &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="NumElements &gt; 0">NumElements={NumElements}, NumChunks={Chunks.Array.ArrayNum}, {NumElementsPerChunk}</DisplayString>
    
        <Expand>
          <IndexListItems Condition="NumElements &gt; 0">
            <Size>NumElements</Size>
            <ValueNode>
              *(
              *(
              ($T1**)Chunks.Array.AllocatorInstance.Data + ($i / NumElementsPerChunk)
              ) + ($i % NumElementsPerChunk)
              )
            </ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
    
      <!-- TSparseArray visualizer -->
      <Type Name="TSparseArray&lt;*,*&gt;">
        <DisplayString Condition="(Data.ArrayNum - NumFreeIndices) &lt;= 0">Empty</DisplayString>
        <DisplayString Condition="Data.ArrayNum &lt;= Data.ArrayMax">Num={Data.ArrayNum - NumFreeIndices}</DisplayString>
        <Expand>
          <IndexListItems Condition="Data.ArrayNum &gt; 0 &amp;&amp; Data.ArrayNum &lt;= Data.ArrayMax">
            <Size>Data.ArrayNum</Size>
            <ValueNode Condition="(AllocationFlags.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocationFlags.SecondaryData.Data)[$i/32]&gt;&gt;$i &amp; 1) != 0">($T1*)Data.AllocatorInstance.Data + $i</ValueNode>
            <ValueNode Condition="(AllocationFlags.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocationFlags.InlineData        )[$i/32]&gt;&gt;$i &amp; 1) != 0">($T1*)Data.AllocatorInstance.Data + $i</ValueNode>
            <ValueNode Condition="(AllocationFlags.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocationFlags.SecondaryData.Data)[$i/32]&gt;&gt;$i &amp; 1) == 0">Invalid</ValueNode>
            <ValueNode Condition="(AllocationFlags.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocationFlags.InlineData        )[$i/32]&gt;&gt;$i &amp; 1) == 0">Invalid</ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
      <!-- TBitArray visualizer -->
      <Type Name="TBitArray&lt;*&gt;">
        <DisplayString Condition="NumBits == 0">Empty</DisplayString>
        <DisplayString Condition="NumBits &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="NumBits &gt; 0">NumBits={NumBits}, MaxBits={MaxBits}</DisplayString>
        <Expand>
          <IndexListItems Condition="NumBits &gt; 0">
            <Size>NumBits</Size>
            <ValueNode Condition="(AllocatorInstance.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocatorInstance.SecondaryData.Data    )[$i/32]&gt;&gt;$i &amp; 1) != 0">1</ValueNode>
            <ValueNode Condition="(AllocatorInstance.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocatorInstance.InlineData            )[$i/32]&gt;&gt;$i &amp; 1) != 0">1</ValueNode>
            <ValueNode Condition="(AllocatorInstance.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocatorInstance.SecondaryData.Data    )[$i/32]&gt;&gt;$i &amp; 1) == 0">0</ValueNode>
            <ValueNode Condition="(AllocatorInstance.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocatorInstance.InlineData            )[$i/32]&gt;&gt;$i &amp; 1) == 0">0</ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
      <!-- TPair visualizer -->
      <Type Name="TPair&lt;*,*&gt;">
        <DisplayString>({Key}, {Value})</DisplayString>
      </Type>
    
      <!-- TSharedPtr visualizer -->
      <Type Name="TSharedPtr&lt;*,*&gt;">
        <DisplayString Condition="Object == 0">Null</DisplayString>
        <DisplayString Condition="Object != 0">Ptr={(void*)Object}, SharedRefs={SharedReferenceCount.ReferenceController->SharedReferenceCount}, WeakRefs={SharedReferenceCount.ReferenceController->WeakReferenceCount}, Object={*Object}</DisplayString>
        <Expand>
          <Item Condition="Object != 0" Name="[SharedReferenceCount]">SharedReferenceCount.ReferenceController->SharedReferenceCount</Item>
          <Item Condition="Object != 0" Name="[WeakReferenceCount]">SharedReferenceCount.ReferenceController->WeakReferenceCount</Item>
          <Item Condition="Object != 0" Name="[Ptr]">(void*)Object</Item>
          <ExpandedItem Condition="Object != 0">*Object</ExpandedItem>
        </Expand>
      </Type>
    
      <!-- TSharedRef visualizer -->
      <Type Name="TSharedRef&lt;*,*&gt;">
        <DisplayString Condition="Object != 0">Ptr={(void*)Object}, SharedRefs={SharedReferenceCount.ReferenceController->SharedReferenceCount}, WeakRefs={SharedReferenceCount.ReferenceController->WeakReferenceCount}, Object={*Object}</DisplayString>
        <Expand>
          <Item Condition="Object != 0" Name="[SharedReferenceCount]">SharedReferenceCount.ReferenceController->SharedReferenceCount</Item>
          <Item Condition="Object != 0" Name="[WeakReferenceCount]">SharedReferenceCount.ReferenceController->WeakReferenceCount</Item>
          <Item Condition="Object != 0" Name="[Ptr]">(void*)Object</Item>
          <ExpandedItem Condition="Object != 0">*Object</ExpandedItem>
        </Expand>
      </Type>
    
      <!-- TWeakPtr visualizer -->
      <Type Name="TWeakPtr&lt;*,*&gt;">
        <DisplayString Condition="Object == 0">Null</DisplayString>
        <DisplayString Condition="WeakReferenceCount.ReferenceController->SharedReferenceCount == 0">Object has been destroyed</DisplayString>
        <DisplayString Condition="Object != 0">Ptr={(void*)Object}, SharedRefs={WeakReferenceCount.ReferenceController->SharedReferenceCount}, WeakRefs={WeakReferenceCount.ReferenceController->WeakReferenceCount}, Object={*Object}</DisplayString>
        <Expand>
          <Item Condition="Object != 0" Name="[SharedReferenceCount]">WeakReferenceCount.ReferenceController->SharedReferenceCount</Item>
          <Item Condition="Object != 0" Name="[WeakReferenceCount]">WeakReferenceCount.ReferenceController->WeakReferenceCount</Item>
          <Item Condition="Object != 0 &amp;&amp; WeakReferenceCount.ReferenceController->SharedReferenceCount > 0" Name="[Ptr]">(void*)Object</Item>
          <ExpandedItem Condition="Object != 0 &amp;&amp; WeakReferenceCount.ReferenceController->SharedReferenceCount > 0">*Object</ExpandedItem>
        </Expand>
      </Type>
    
    
      <!-- TMapBase visualizer -->
      <Type Name="TMapBase&lt;*,*,*,*&gt;">
        <DisplayString Condition="Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices &lt;= 0">Empty</DisplayString>
        <DisplayString Condition="Pairs.Elements.Data.ArrayNum &lt;= Pairs.Elements.Data.ArrayMax" >Num={Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices}</DisplayString>
        <Expand>
          <IndexListItems Condition="Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices &gt; 0 &amp;&amp; Pairs.Elements.Data.ArrayNum &lt;= Pairs.Elements.Data.ArrayMax">
            <Size>Pairs.Elements.Data.ArrayNum</Size>
            <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]&gt;&gt;$i &amp; 1) != 0">((TSetElement&lt;TPair&lt;$T1,$T2&gt; &gt; *)Pairs.Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode>
            <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Pairs.Elements.AllocationFlags.AllocatorInstance.InlineData        )[$i/32]&gt;&gt;$i &amp; 1) != 0">((TSetElement&lt;TPair&lt;$T1,$T2&gt; &gt; *)Pairs.Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode>
            <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]&gt;&gt;$i &amp; 1) == 0">Invalid</ValueNode>
            <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Pairs.Elements.AllocationFlags.AllocatorInstance.InlineData        )[$i/32]&gt;&gt;$i &amp; 1) == 0">Invalid</ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
      <!-- TSet visualizer -->
      <Type Name="TSet&lt;*,*,*&gt;">
        <DisplayString Condition="Elements.Data.ArrayNum - Elements.NumFreeIndices &lt;= 0">Empty</DisplayString>
        <DisplayString Condition="Elements.Data.ArrayNum &lt;= Elements.Data.ArrayMax">Num={Elements.Data.ArrayNum - Elements.NumFreeIndices}</DisplayString>
        <Expand>
          <IndexListItems Condition="Elements.Data.ArrayNum - Elements.NumFreeIndices &gt; 0 &amp;&amp; Elements.Data.ArrayNum &lt;= Elements.Data.ArrayMax">
            <Size>Elements.Data.ArrayNum</Size>
            <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]&gt;&gt;$i &amp; 1) != 0">((TSetElement &lt;$T1&gt; *)Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode>
            <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Elements.AllocationFlags.AllocatorInstance.InlineData        )[$i/32]&gt;&gt;$i &amp; 1) != 0">((TSetElement &lt;$T1&gt; *)Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode>
            <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]&gt;&gt;$i &amp; 1) == 0">Invalid</ValueNode>
            <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Elements.AllocationFlags.AllocatorInstance.InlineData)[$i/32]&gt;&gt;$i &amp; 1) == 0">Invalid</ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
      <!-- FWeakObjectPtr|TWeakObjectPtr<*>|TAutoWeakObjectPtr<*> visualizer -->
      <Type Name="FWeakObjectPtr|TWeakObjectPtr&lt;*&gt;|TAutoWeakObjectPtr&lt;*&gt;">
        <DisplayString Condition="ObjectSerialNumber &lt; 1">NULL</DisplayString>
        <DisplayString Condition="*((*(*GSerialNumberBlocksForDebugVisualizers + (ObjectIndex / 0x4000))) + (ObjectIndex % 0x4000)) != ObjectSerialNumber">STALE</DisplayString>
        <DisplayString>{GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]}</DisplayString>
        <Expand>
          <ExpandedItem>GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]</ExpandedItem>
        </Expand>
      </Type>
    
      <!-- FSubobjectPtr|TSubobjectPtr visualizer -->
      <Type Name="FSubobjectPtr|TSubobjectPtr&lt;*&gt;">
        <DisplayString>{Object}</DisplayString>
      </Type>
    
      <!-- TOptional visualizer -->
      <Type Name="TOptional&lt;*&gt;">
        <DisplayString Condition="!bIsSet">Unset</DisplayString>
        <DisplayString Condition="bIsSet">Set: {{{*($T1*)&amp;Value}}}</DisplayString>
        <Expand>
          <ExpandedItem Condition="bIsSet">*($T1*)&amp;Value</ExpandedItem>
        </Expand>
      </Type>
    
      <!-- TFunction visualizer -->
      <Type Name="UE4Function_Private::TDebugHelper&lt;*&gt;">
        <DisplayString>{*Ptr}</DisplayString>
        <Expand>
          <ExpandedItem>*Ptr</ExpandedItem>
        </Expand>
      </Type>
      <Type Name="TFunctionRef&lt;*&gt;">
        <DisplayString Condition="Ptr">{DebugPtrStorage}</DisplayString>
        <DisplayString Condition="!Ptr">Unset</DisplayString>
        <Expand>
          <ExpandedItem Condition="Ptr">DebugPtrStorage</ExpandedItem>
        </Expand>
      </Type>
    
    </AutoVisualizer>
    UE4.natvis

    针对于PS4版本的debug,需要将以下两个文件拷贝到:c:UsersusernameDocumentsSCEorbis-debugger :

    <?xml version="1.0" encoding="utf-8"?>
    <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
    
      <!-- UE3 Visualizers -->
      <!-- Copy this into $USERPROFILE/Documents/SCE/orbis-debugger -->
    
      <!-- FString visualizer -->
      <Type Name="UE3::FString">
        <DisplayString Condition="ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &lt; ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &gt;= ArrayNum">{AllocatorInstance.Data,su}</DisplayString>
        <StringView Condition="ArrayMax &gt;= ArrayNum">AllocatorInstance.Data,su</StringView>
      </Type>
    
      <!-- FName visualizer -->
      <Type Name="UE3::FName">
        <DisplayString Condition="Index &gt;= Names.ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="Index &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="0 == (((((::UE3::FNameEntry**) Names.AllocatorInstance.Data)[Index])->Index) &amp; 1)">{(((::UE3::FNameEntry**) Names.AllocatorInstance.Data)[Index])->AnsiName,s}_{Number - 1}</DisplayString>
        <DisplayString Condition="1 == (((((::UE3::FNameEntry**) Names.AllocatorInstance.Data)[Index])->Index) &amp; 1)">{(((::UE3::FNameEntry**) Names.AllocatorInstance.Data)[Index])->UniName,su}_{Number - 1}</DisplayString>
      </Type>
    
      <!-- TArray visualizer -->
      <Type Name="UE3::TArray&lt;*,*&gt;">
        <DisplayString Condition="ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &lt; ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &gt;= ArrayNum">Num={ArrayNum}</DisplayString>
        <Expand>
          <ArrayItems>
            <Size>ArrayNum</Size>
            <ValuePointer>($T1 *) AllocatorInstance.Data</ValuePointer>
          </ArrayItems>
        </Expand>
      </Type>
      <!-- AC TArray has 3 template parameters -->
      <Type Name="UE3::TArray&lt;*,*,*&gt;">
        <DisplayString Condition="ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &lt; ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &gt;= ArrayNum">Num={ArrayNum}</DisplayString>
        <Expand>
          <ArrayItems>
            <Size>ArrayNum</Size>
            <ValuePointer>($T1 *) AllocatorInstance.Data</ValuePointer>
          </ArrayItems>
        </Expand>
      </Type>
    
      <!-- TSparseArray visualizer -->
      <Type Name="UE3::TSparseArray&lt;*,*&gt;">
        <DisplayString Condition="Data.ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="Data.ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="Data.ArrayMax &lt; Data.ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="Data.ArrayMax &gt;= Data.ArrayNum">Num={Data.ArrayNum}</DisplayString>
        <Expand>
          <ArrayItems Condition="Data.ArrayNum &lt;= Data.ArrayMax">
            <Size>Data.ArrayNum</Size>
            <ValuePointer>(::$T1 *) Data.AllocatorInstance.Data</ValuePointer>
          </ArrayItems>
        </Expand>
      </Type>
    
      <!-- TMapBase::FPair visualizer -->
      <Type Name="UE3::TMapBase&lt;*,*,*,*,*&gt;::FPair">
          <DisplayString>({Key}, {Value})</DisplayString>
      </Type>
    
      <!-- TMapBase visualizer -->
      <Type Name="UE3::TMapBase&lt;*,*,*,*,*&gt;">
        <DisplayString Condition="Pairs.Elements.Data.ArrayNum &lt;= 0">Empty</DisplayString>
        <DisplayString Condition="Pairs.Elements.Data.ArrayNum &lt;= Pairs.Elements.Data.ArrayMax">Num={Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices}</DisplayString>
        <Expand>
          <IndexListItems Condition="Pairs.Elements.Data.ArrayNum &gt; 0 &amp;&amp; Pairs.Elements.Data.ArrayNum &lt;= Pairs.Elements.Data.ArrayMax">
            <Size>Pairs.Elements.Data.ArrayNum</Size>
            <ValueNode>((TSet&lt;TMapBase&lt;$T1,$T2,$T3,$T4&gt;::FPair,TMapBase&lt;$T1,$T2,$T3,$T4&gt;::KeyFuncs,$T4&gt;::FElement *) Pairs.Elements.Data.AllocatorInstance.Data + $i)-&gt;Value</ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
      <!-- GFx GAtomicValueBase visualizer -->
      <Type Name="GAtomicValueBase">
        <DisplayString>{Value}</DisplayString>
      </Type>
    
      <!-- UObject visualizer -->
      <Type Name="UE3::UObject">
        <DisplayString Condition="0 != Outer">(Name={Name}, Outer={Outer})</DisplayString>
        <DisplayString Condition="0 == Outer">(Name={Name})</DisplayString>
      </Type>
    
    </AutoVisualizer>
    PS4UE3.natvis
    <?xml version="1.0" encoding="utf-8"?>
    <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
    
      <!-- Epic Games, Inc. UE4 Visualizers -->
      <!-- Copy this into DocumentsSCEorbis-debugger -->
    
      <!-- FString visualizer -->
      <Type Name="FString">
        <DisplayString Condition="Data.ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="Data.ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="Data.ArrayMax &lt; Data.ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="Data.ArrayMax &gt;= Data.ArrayNum">{Data.AllocatorInstance.Data,su}</DisplayString>
        <StringView Condition="Data.ArrayMax &gt;= Data.ArrayNum">Data.AllocatorInstance.Data,su</StringView>
      </Type>
    
      <!-- FName visualizer -->
      <Type Name="FName">
        <DisplayString Condition="ComparisonIndex &gt;= 2097152">Invalid</DisplayString>
        <DisplayString Condition="ComparisonIndex &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="(ComparisonIndex &lt; 2097152) &amp;&amp; (Number &gt; 0)">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[ComparisonIndex / 16384][ComparisonIndex % 16384]))->AnsiName,s}_{Number-1}</DisplayString>
        <DisplayString Condition="ComparisonIndex &lt; 2097152">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[ComparisonIndex / 16384][ComparisonIndex % 16384]))->AnsiName,s}</DisplayString>
        <StringView Condition="ComparisonIndex &lt; 2097152">((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[ComparisonIndex / 16384][ComparisonIndex % 16384]))->AnsiName</StringView>
      </Type>
    
      <Type Name="FMinimalName">
        <DisplayString Condition="Index &gt;= 2097152">Invalid</DisplayString>
        <DisplayString Condition="Index &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="(Index &lt; 2097152) &amp;&amp; (Number &gt; 0)">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[Index / 16384][Index % 16384]))->AnsiName}_{Number-1}</DisplayString>
        <DisplayString Condition="Index &lt; 2097152">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[Index / 16384][Index % 16384]))->AnsiName}</DisplayString>
        <StringView Condition="Index &lt; 2097152">((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[Index / 16384][Index % 16384]))->AnsiName</StringView>
      </Type>
    
      <!-- FStatMessage visualizer @see Stats2.h -->
      <Type Name="FStatMessage">
        <!--ST_None=1-->
        <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&amp;0x7) == 1" >{{NoneType NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString>
        <!--ST_int64=2-->
        <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&amp;0x7) == 2" >{{Int64={DebugStatData.Cycles},C={DebugStatData.CCAndDuration[0]},D={DebugStatData.CCAndDuration[1]} NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString>
        <!--ST_double=3-->
        <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&amp;0x7) == 3" >{{Float={DebugStatData.Float} NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString>
        <!--ST_FName=4-->
        <!--ST_Ptr=5-->
        <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&amp;0x7) == 5" >{{Ptr={DebugStatData.Ptr} NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString>
      </Type>
    
      <Type Name="FVector_NetQuantize">
        <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString>
      </Type>
    
      <Type Name="FVector_NetQuantize10">
        <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString>
      </Type>
    
      <Type Name="FVector_NetQuantize100">
        <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString>
      </Type>
    
      <Type Name="FVector_NetQuantizeNormal">
        <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString>
      </Type>
    
      <!-- TEnumAsByte visualizer -->
      <Type Name="TEnumAsByte&lt;*&gt;">
        <DisplayString>{($T1)Value}</DisplayString>
      </Type>
    
      <!-- UObjectBase visualizer -->
      <Type Name="UObjectBase">
        <DisplayString>(Name={Name}, Outer={Outer})</DisplayString>
      </Type>
    
      <!-- TArray<*,TFixedAllocator<*> > visualizer -->
      <Type Name="TArray&lt;*,TFixedAllocator&lt;*&gt;&gt;">
        <DisplayString Condition="ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &lt; ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &gt;= ArrayNum">Num={ArrayNum}</DisplayString>
        <Expand>
          <ArrayItems Condition="ArrayNum &lt;= ArrayMax">
            <Size>ArrayNum</Size>
            <ValuePointer>($T1*)AllocatorInstance.InlineData</ValuePointer>
          </ArrayItems>
        </Expand>
      </Type>
    
      <!-- TArray<*,TInlineAllocator<*,*> > visualizer -->
      <Type Name="TArray&lt;*,TInlineAllocator&lt;*,*&gt;&gt;">
        <DisplayString Condition="ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &lt; ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &gt;= ArrayNum">Num={ArrayNum}</DisplayString>
        <Expand>
          <ArrayItems Condition="ArrayNum &lt;= ArrayMax">
            <Size>ArrayNum</Size>
            <ValuePointer Condition="AllocatorInstance.SecondaryData.Data == 0">($T1*)AllocatorInstance.InlineData</ValuePointer>
            <ValuePointer Condition="AllocatorInstance.SecondaryData.Data != 0">($T1*)AllocatorInstance.SecondaryData.Data</ValuePointer>
          </ArrayItems>
        </Expand>
      </Type>
    
      <!-- TArray visualizer -->
      <Type Name="TArray&lt;*,*&gt;">
        <DisplayString Condition="ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &lt; ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="ArrayMax &gt;= ArrayNum">Num={ArrayNum}</DisplayString>
        <Expand>
          <ArrayItems Condition="ArrayNum &lt;= ArrayMax">
            <Size>ArrayNum</Size>
            <ValuePointer>(::$T1*)AllocatorInstance.Data</ValuePointer>
          </ArrayItems>
        </Expand>
      </Type>
    
      <!-- TIndirectArray visualizer -->
      <Type Name="TIndirectArray&lt;*,*&gt;">
        <DisplayString Condition="Array.ArrayNum == 0">Empty</DisplayString>
        <DisplayString Condition="Array.ArrayNum &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="Array.ArrayMax &lt; Array.ArrayNum">Invalid</DisplayString>
        <DisplayString Condition="Array.ArrayMax &gt;= Array.ArrayNum">Num={Array.ArrayNum}</DisplayString>
        <Expand>
          <IndexListItems Condition="Array.ArrayNum &lt;= Array.ArrayMax">
            <Size>Array.ArrayNum</Size>
            <ValueNode>*(($T1**)Array.AllocatorInstance.Data)[$i]</ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
      <!-- TChunkedArray visualizer -->
      <Type Name="TChunkedArray&lt;*,*&gt;">
        <DisplayString Condition="NumElements == 0">Empty</DisplayString>
        <DisplayString Condition="NumElements &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="NumElements &gt; 0">NumElements={NumElements}, NumChunks={Chunks.Array.ArrayNum}, {NumElementsPerChunk}</DisplayString>
    
        <Expand>
          <IndexListItems Condition="NumElements &gt; 0">
            <Size>NumElements</Size>
            <ValueNode>
              *(
              *(
              ($T1**)Chunks.Array.AllocatorInstance.Data + ($i / NumElementsPerChunk)
              ) + ($i % NumElementsPerChunk)
              )
            </ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
    
      <!-- TSparseArray visualizer -->
      <Type Name="TSparseArray&lt;*,*&gt;">
        <DisplayString Condition="(Data.ArrayNum - NumFreeIndices) &lt;= 0">Empty</DisplayString>
        <DisplayString Condition="Data.ArrayNum &lt;= Data.ArrayMax">Num={Data.ArrayNum - NumFreeIndices}</DisplayString>
        <Expand>
          <IndexListItems Condition="Data.ArrayNum &gt; 0 &amp;&amp; Data.ArrayNum &lt;= Data.ArrayMax">
            <Size>Data.ArrayNum</Size>
            <ValueNode Condition="(AllocationFlags.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocationFlags.SecondaryData.Data)[$i/32]&gt;&gt;$i &amp; 1) != 0">($T1*)Data.AllocatorInstance.Data + $i</ValueNode>
            <ValueNode Condition="(AllocationFlags.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocationFlags.InlineData        )[$i/32]&gt;&gt;$i &amp; 1) != 0">($T1*)Data.AllocatorInstance.Data + $i</ValueNode>
            <ValueNode Condition="(AllocationFlags.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocationFlags.SecondaryData.Data)[$i/32]&gt;&gt;$i &amp; 1) == 0">Invalid</ValueNode>
            <ValueNode Condition="(AllocationFlags.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocationFlags.InlineData        )[$i/32]&gt;&gt;$i &amp; 1) == 0">Invalid</ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
      <!-- TBitArray visualizer -->
      <Type Name="TBitArray&lt;*&gt;">
        <DisplayString Condition="NumBits == 0">Empty</DisplayString>
        <DisplayString Condition="NumBits &lt; 0">Invalid</DisplayString>
        <DisplayString Condition="NumBits &gt; 0">NumBits={NumBits}, MaxBits={MaxBits}</DisplayString>
        <Expand>
          <IndexListItems Condition="NumBits &gt; 0">
            <Size>NumBits</Size>
            <ValueNode Condition="(AllocatorInstance.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocatorInstance.SecondaryData.Data    )[$i/32]&gt;&gt;$i &amp; 1) != 0">1</ValueNode>
            <ValueNode Condition="(AllocatorInstance.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocatorInstance.InlineData            )[$i/32]&gt;&gt;$i &amp; 1) != 0">1</ValueNode>
            <ValueNode Condition="(AllocatorInstance.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocatorInstance.SecondaryData.Data    )[$i/32]&gt;&gt;$i &amp; 1) == 0">0</ValueNode>
            <ValueNode Condition="(AllocatorInstance.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(AllocatorInstance.InlineData            )[$i/32]&gt;&gt;$i &amp; 1) == 0">0</ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
      <!-- TPair visualizer -->
      <Type Name="TPair&lt;*,*&gt;">
        <DisplayString>({Key}, {Value})</DisplayString>
      </Type>
    
      <!-- TSharedPtr visualizer -->
      <Type Name="TSharedPtr&lt;*,*&gt;">
        <DisplayString Condition="Object == 0">Null</DisplayString>
        <DisplayString Condition="Object != 0">Ptr={(void*)Object}, SharedRefs={SharedReferenceCount.ReferenceController->SharedReferenceCount}, WeakRefs={SharedReferenceCount.ReferenceController->WeakReferenceCount}, Object={*Object}</DisplayString>
        <Expand>
          <Item Condition="Object != 0" Name="[SharedReferenceCount]">SharedReferenceCount.ReferenceController->SharedReferenceCount</Item>
          <Item Condition="Object != 0" Name="[WeakReferenceCount]">SharedReferenceCount.ReferenceController->WeakReferenceCount</Item>
          <Item Condition="Object != 0" Name="[Ptr]">(void*)Object</Item>
          <ExpandedItem Condition="Object != 0">*Object</ExpandedItem>
        </Expand>
      </Type>
    
      <!-- TSharedRef visualizer -->
      <Type Name="TSharedRef&lt;*,*&gt;">
        <DisplayString Condition="Object != 0">Ptr={(void*)Object}, SharedRefs={SharedReferenceCount.ReferenceController->SharedReferenceCount}, WeakRefs={SharedReferenceCount.ReferenceController->WeakReferenceCount}, Object={*Object}</DisplayString>
        <Expand>
          <Item Condition="Object != 0" Name="[SharedReferenceCount]">SharedReferenceCount.ReferenceController->SharedReferenceCount</Item>
          <Item Condition="Object != 0" Name="[WeakReferenceCount]">SharedReferenceCount.ReferenceController->WeakReferenceCount</Item>
          <Item Condition="Object != 0" Name="[Ptr]">(void*)Object</Item>
          <ExpandedItem Condition="Object != 0">*Object</ExpandedItem>
        </Expand>
      </Type>
    
      <!-- TWeakPtr visualizer -->
      <Type Name="TWeakPtr&lt;*,*&gt;">
        <DisplayString Condition="Object == 0">Null</DisplayString>
        <DisplayString Condition="WeakReferenceCount.ReferenceController->SharedReferenceCount == 0">Object has been destroyed</DisplayString>
        <DisplayString Condition="Object != 0">Ptr={(void*)Object}, SharedRefs={WeakReferenceCount.ReferenceController->SharedReferenceCount}, WeakRefs={WeakReferenceCount.ReferenceController->WeakReferenceCount}, Object={*Object}</DisplayString>
        <Expand>
          <Item Condition="Object != 0" Name="[SharedReferenceCount]">WeakReferenceCount.ReferenceController->SharedReferenceCount</Item>
          <Item Condition="Object != 0" Name="[WeakReferenceCount]">WeakReferenceCount.ReferenceController->WeakReferenceCount</Item>
          <Item Condition="Object != 0 &amp;&amp; WeakReferenceCount.ReferenceController->SharedReferenceCount > 0" Name="[Ptr]">(void*)Object</Item>
          <ExpandedItem Condition="Object != 0 &amp;&amp; WeakReferenceCount.ReferenceController->SharedReferenceCount > 0">*Object</ExpandedItem>
        </Expand>
      </Type>
    
    
      <!-- TMapBase visualizer -->
      <Type Name="TMapBase&lt;*,*,*,*,*&gt;">
        <DisplayString Condition="Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices &lt;= 0">Empty</DisplayString>
        <DisplayString Condition="Pairs.Elements.Data.ArrayNum &lt;= Pairs.Elements.Data.ArrayMax" >Num={Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices}</DisplayString>
        <Expand>
          <IndexListItems Condition="Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices &gt; 0 &amp;&amp; Pairs.Elements.Data.ArrayNum &lt;= Pairs.Elements.Data.ArrayMax">
            <Size>Pairs.Elements.Data.ArrayNum</Size>
            <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]&gt;&gt;$i &amp; 1) != 0">((TSetElement&lt;TPair&lt;$T1,$T2&gt; &gt; *)Pairs.Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode>
            <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Pairs.Elements.AllocationFlags.AllocatorInstance.InlineData        )[$i/32]&gt;&gt;$i &amp; 1) != 0">((TSetElement&lt;TPair&lt;$T1,$T2&gt; &gt; *)Pairs.Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode>
            <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]&gt;&gt;$i &amp; 1) == 0">Invalid</ValueNode>
            <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Pairs.Elements.AllocationFlags.AllocatorInstance.InlineData        )[$i/32]&gt;&gt;$i &amp; 1) == 0">Invalid</ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
      <!-- TSet visualizer -->
      <Type Name="TSet&lt;*,*,*&gt;">
        <DisplayString Condition="Elements.Data.ArrayNum - Elements.NumFreeIndices &lt;= 0">Empty</DisplayString>
        <DisplayString Condition="Elements.Data.ArrayNum &lt;= Elements.Data.ArrayMax">Num={Elements.Data.ArrayNum - Elements.NumFreeIndices}</DisplayString>
        <Expand>
          <IndexListItems Condition="Elements.Data.ArrayNum - Elements.NumFreeIndices &gt; 0 &amp;&amp; Elements.Data.ArrayNum &lt;= Elements.Data.ArrayMax">
            <Size>Elements.Data.ArrayNum</Size>
            <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]&gt;&gt;$i &amp; 1) != 0">((TSetElement &lt;$T1&gt; *)Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode>
            <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Elements.AllocationFlags.AllocatorInstance.InlineData        )[$i/32]&gt;&gt;$i &amp; 1) != 0">((TSetElement &lt;$T1&gt; *)Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode>
            <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]&gt;&gt;$i &amp; 1) == 0">Invalid</ValueNode>
            <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) &amp;&amp; (reinterpret_cast&lt;uint32*&gt;(Elements.AllocationFlags.AllocatorInstance.InlineData)[$i/32]&gt;&gt;$i &amp; 1) == 0">Invalid</ValueNode>
          </IndexListItems>
        </Expand>
      </Type>
    
      <!-- FWeakObjectPtr|TWeakObjectPtr<*>|TAutoWeakObjectPtr<*> visualizer -->
      <Type Name="FWeakObjectPtr">
        <DisplayString Condition="ObjectSerialNumber &lt; 1">NULL</DisplayString>
        <DisplayString Condition="*((*(*GSerialNumberBlocksForDebugVisualizers + (ObjectIndex / 0x4000))) + (ObjectIndex % 0x4000)) != ObjectSerialNumber">STALE</DisplayString>
        <DisplayString>{GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]}</DisplayString>
        <Expand>
          <ExpandedItem>GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]</ExpandedItem>
        </Expand>
      </Type>
    
      <Type Name="TWeakObjectPtr&lt;*&gt;">
        <DisplayString Condition="ObjectSerialNumber &lt; 1">NULL</DisplayString>
        <DisplayString Condition="*((*(*GSerialNumberBlocksForDebugVisualizers + (ObjectIndex / 0x4000))) + (ObjectIndex % 0x4000)) != ObjectSerialNumber">STALE</DisplayString>
        <DisplayString>{GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]}</DisplayString>
        <Expand>
          <ExpandedItem>GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]</ExpandedItem>
        </Expand>
      </Type>
    
      <Type Name="TAutoWeakObjectPtr&lt;*&gt;">
        <DisplayString Condition="ObjectSerialNumber &lt; 1">NULL</DisplayString>
        <DisplayString Condition="*((*(*GSerialNumberBlocksForDebugVisualizers + (ObjectIndex / 0x4000))) + (ObjectIndex % 0x4000)) != ObjectSerialNumber">STALE</DisplayString>
        <DisplayString>{GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]}</DisplayString>
        <Expand>
          <ExpandedItem>GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]</ExpandedItem>
        </Expand>
      </Type>
    
      <!-- FSubobjectPtr|TSubobjectPtr visualizer -->
      <Type Name="FSubobjectPtr">
        <DisplayString>{Object}</DisplayString>
      </Type>
      <Type Name="TSubobjectPtr&lt;*&gt;">
        <DisplayString>{Object}</DisplayString>
      </Type>
    
      <!-- TOptional visualizer -->
      <Type Name="TOptional&lt;*&gt;">
        <DisplayString Condition="!bIsSet">Unset</DisplayString>
        <DisplayString Condition="bIsSet">Set: {{{*($T1*)&amp;Value}}}</DisplayString>
        <Expand>
          <ExpandedItem Condition="bIsSet">*($T1*)&amp;Value</ExpandedItem>
        </Expand>
      </Type>
    
      <!-- TFunction visualizer -->
      <Type Name="UE4Function_Private::TDebugHelper&lt;*&gt;">
        <DisplayString>{*Ptr}</DisplayString>
        <Expand>
          <ExpandedItem>*Ptr</ExpandedItem>
        </Expand>
      </Type>
      <Type Name="TFunctionRef&lt;*&gt;">
        <DisplayString Condition="Ptr">{DebugPtrStorage}</DisplayString>
        <DisplayString Condition="!Ptr">Unset</DisplayString>
        <Expand>
          <ExpandedItem Condition="Ptr">DebugPtrStorage</ExpandedItem>
        </Expand>
      </Type>
    
    </AutoVisualizer>
    PS4UE4.natvis

    下面的sh执行文件可以用于一键执行:

    #!/bin/bash
    
    cp_args="-v --preserve=timestamps"
    cp $cp_args UE{3,4}.natvis    "$USERPROFILE/Documents/Visual Studio 2012/Visualizers"
    cp $cp_args UE{3,4}.natvis    "$USERPROFILE/Documents/Visual Studio 2013/Visualizers"
    cp $cp_args PS4UE{3,4}.natvis "$USERPROFILE/Documents/SCE/orbis-debugger"

    注意在以上几个文件中更改自己所使用的VS版本号使之与本机VS版本一致; 

  • 相关阅读:
    第六章 (3)CreateThread函数
    第六章(5)C/C++运行期库
    自己去除迅雷广告
    第六章(4)终止线程的运行
    第四章 进程(7)CreateProcess函数详解
    第六章(6)进程ID的相关函数
    第六章 线程的基础知识
    第四章 进程(5)进程的当前驱动器和目录
    第四章 进程(6)CreateProcess函数详解
    第六章 (2)线程函数
  • 原文地址:https://www.cnblogs.com/DeanWang/p/7070499.html
Copyright © 2020-2023  润新知