Skip to content

Fix NullReferenceException in SegmentedList.Add during large heap snapshots#2391

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/fix-nullreferenceexception-heap-snapshot
Draft

Fix NullReferenceException in SegmentedList.Add during large heap snapshots#2391
Copilot wants to merge 2 commits intomainfrom
copilot/fix-nullreferenceexception-heap-snapshot

Conversation

Copy link
Contributor

Copilot AI commented Mar 20, 2026

Taking a heap snapshot on large heaps (100M+ objects) throws System.NullReferenceException inside SegmentedList<T>.Add via Graph.SetNodeTypeAndSizeNode.WriteCompressedInt.

Root Cause

SegmentedMemoryStreamWriter.Clear() was replacing the backing bytes list with a brand-new empty SegmentedList<byte>:

// Before
public virtual void Clear() { bytes = new SegmentedList<byte>(131_072); }

Graph.ClearWorker() creates the writer with a large initial capacity (m_expectedNodeCount * 8, up to ~1 GB for 128M-node graphs) and then immediately calls m_writer.Clear(), discarding that entire pre-allocation. The replacement list starts with items = null. When Write(byte) is JIT-inlined into WriteCompressedInt, calling bytes.Add(value) on this fresh null-items list under memory pressure results in a NullReferenceException inside SegmentedList.Add. There's also a segment-size inconsistency: the constructor uses segmentSize = 65_536; Clear() was creating a new list with segmentSize = 131_072.

Fix

Reset the count of the existing bytes list rather than replacing it:

// After
public virtual void Clear() { bytes.Count = 0; }

This preserves the pre-allocated buffer (eliminating the wasted ~1 GB allocation and the items = null state), keeps the segment size consistent, and removes the NullReferenceException risk.

Changes

  • src/FastSerialization/SegmentedMemoryStreamWriter.cs — one-line fix to Clear()
  • src/FastSerialization.Tests/SegmentedMemoryStreamWriterTests.cs — new tests covering Clear() semantics, write/read round-trips, multiple clear cycles, and cross-segment-boundary writes
Original prompt

This section details on the original issue you should resolve

<issue_title>System.NullReferenceException while taking heap snapshot</issue_title>
<issue_description>Version: P2.0.42 (64 bit)
Max Dump K objects: 250
Freeze: No
Save ETL: No

Tail of log:

1070.1s: Dumped 114,354,847 objects, max_dump_limit 134,217,716 Dumper heap Size 7,384MB
HeapDump Error: System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Collections.Generic.SegmentedList`1.Add(T item)
   at Graphs.Node.WriteCompressedInt(SegmentedMemoryStreamWriter writer, Int32 value)
   at Graphs.Graph.SetNodeTypeAndSize(NodeIndex nodeIndex, NodeTypeIndex typeIndex, Int32 sizeInBytes)
   at Graphs.Graph.SetNode(NodeIndex nodeIndex, NodeTypeIndex typeIndex, Int32 sizeInBytes, GrowableArray`1 children)
   at GCHeapDumper.DumpAllSegments()
   at GCHeapDumper.DumpDotNetHeapDataWorker(ClrHeap heap, ICorDebugProcess& debugProcess, Boolean isDump, Double retryScale)
   at GCHeapDumper.DumpDotNetHeapData(ClrHeap heap, ICorDebugProcess& debugProcess, Boolean isDump)
   at GCHeapDumper.TryGetDotNetDump(Int32 processID)
   at GCHeapDumper.CaptureLiveHeapDump(Int32 processID)
   at GCHeapDumper.DumpLiveHeap(Int32 processID)
   at Program.MainWorker(String[] args)


Completed: Dumping GC Heap to c:\temp\20190613.gcDump   (Elapsed Time: 1071.709 sec)
Error: HeapDump failed with exit code 1

</issue_description>

Comments on the Issue (you are @copilot in this section)

Custom agent used: Issue Triager
Investigates, reproduces, and fixes issues in PerfView and TraceEvent.


⌨️ Start Copilot coding agent tasks without leaving your editor — available in VS Code, Visual Studio, JetBrains IDEs and Eclipse.

…pshots

SegmentedMemoryStreamWriter.Clear() was discarding the pre-allocated
bytes buffer and replacing it with a new empty SegmentedList. For large
heap dumps (128M+ objects), this caused:
- The ~1GB pre-allocation from the constructor to be wasted immediately
- A new list with items=null and a different segmentSize (131072 vs 65536)
- NullReferenceException in SegmentedList.Add when the fresh empty list
  was used under memory pressure

Fix: reset bytes.Count = 0 to reuse the existing pre-allocated buffer.

Also adds SegmentedMemoryStreamWriterTests covering Clear() behavior,
write/read round-trips, and cross-segment-boundary writes.

Co-authored-by: brianrob <6210322+brianrob@users.noreply.github.com>
Agent-Logs-Url: https://github.com/microsoft/perfview/sessions/de8bc1dc-8c49-45aa-80a2-0cd73d4a3536
Copilot AI changed the title [WIP] Fix System.NullReferenceException while taking heap snapshot Fix NullReferenceException in SegmentedList.Add during large heap snapshots Mar 20, 2026
Copilot AI requested a review from brianrob March 20, 2026 22:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

System.NullReferenceException while taking heap snapshot

2 participants