From d926f81d571ae3af7768da713d0e00fc60ad9c46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Anic=CC=81?= Date: Sun, 6 Aug 2023 20:20:42 +0200 Subject: [PATCH 1/2] add failing test This test brings Heap into endless loop. --- src/heap.zig | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/heap.zig b/src/heap.zig index 4c004b3..1ce54dc 100644 --- a/src/heap.zig +++ b/src/heap.zig @@ -340,3 +340,39 @@ test "heap: million values" { try testing.expect(h.deleteMin() == null); try testing.expect(count == NUM_TIMERS); } + +test "heap: dangling next pointer" { + const testing = std.testing; + const Elem = struct { + const Self = @This(); + value: usize = 0, + heap: IntrusiveField(Self) = .{}, + }; + + const Heap = Intrusive(Elem, void, (struct { + fn less(ctx: void, a: *Elem, b: *Elem) bool { + _ = ctx; + return a.value < b.value; + } + }).less); + + var a: Elem = .{ .value = 2 }; + var b: Elem = .{ .value = 4 }; + var c: Elem = .{ .value = 5 }; + var d: Elem = .{ .value = 1 }; + var e: Elem = .{ .value = 3 }; + + var h: Heap = .{ .context = {} }; + h.insert(&a); + h.insert(&b); + h.insert(&c); + h.insert(&d); + h.insert(&e); + + try testing.expect(h.deleteMin().?.value == 1); + try testing.expect(h.deleteMin().?.value == 2); + try testing.expect(h.deleteMin().?.value == 3); + try testing.expect(h.deleteMin().?.value == 4); + try testing.expect(h.deleteMin().?.value == 5); + try testing.expect(h.deleteMin() == null); +} From 0fbc672a52f12fb729a63a52f8bbb238c34cf3c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Anic=CC=81?= Date: Sun, 6 Aug 2023 20:21:25 +0200 Subject: [PATCH 2/2] fix failing test --- src/heap.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/heap.zig b/src/heap.zig index 1ce54dc..37d8d4d 100644 --- a/src/heap.zig +++ b/src/heap.zig @@ -109,6 +109,7 @@ pub fn Intrusive( if (b.heap.next) |b_next| { a.heap.next = b_next; b_next.heap.prev = a; + b.heap.next = null; } // If A has a child, then B becomes the leftmost sibling