Repository navigation
Keep the reservation when the array is emptied - #18
Open
lukewilliamboswell wants to merge 1 commit into
Open
lukewilliamboswell wants to merge 1 commit into
lukewilliamboswell wants to merge 1 commit into
Conversation
`ensureTotalCapacity` assigned the requested capacity unconditionally, so `resize` to a shorter length lowered `capacity` without releasing anything. A capacity of zero is how the array records that it holds no reservation, so after `resize(0)` the next growth reserved a fresh address range and abandoned the previous one together with its committed pages, and `deinit` skipped the release as well. `shrinkAndFree(0)` stranded the reservation the same way after decommitting it. `ensureTotalCapacity` now only ever raises the capacity, and `shrinkAndFree(0)` releases the reservation like `clearAndFree`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lukewilliamboswell
marked this pull request as ready for review
October 8, 2026 21:14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Emptying a
StableArraywithresize(0)and then growing it again leaks the whole reservation.The bug
A capacity of zero is how the array records that it has no reservation yet.
ensureTotalCapacityended with an unconditionalself.capacity = new_capacity, so it also lowered the capacity whenever it was asked for less than it already had. Afterresize(0):capacity == 0, reserves a fresh range, and overwritesitems.ptr, abandoning the old range and its committed pages;deinit/clearAndFreeskip the release, because they only free whencapacity > 0.shrinkAndFree(0)strands the reservation the same way after decommitting it.The fix
ensureTotalCapacityreturns early unless it is asked to grow, so it never lowers the capacity.shrinkAndFree(0)releases the reservation, asclearAndFreedoes.resizeto a shorter length now keeps the capacity, which is whatstd.ArrayList.resizedoes.Tests
Three new tests; each fails on
mainand passes with the change:resizeto a shorter length and to zero keeps the capacity and the sameitems.ptr.resize(0)cycle repeated more times than the address space could hold if each cycle leaked a reservation.shrinkAndFree(0).Run with Zig 0.16.0 on Windows:
zig build test,zig build -Dtarget=x86-windows-gnu test, and-Doptimize=ReleaseSafeall pass 10/10. I have not run the Linux or macOS jobs locally.How it showed up
bytebox's validator resets
control_typeswithresize(0)after every function body, so decoding a module leaked one 1 MiB reservation per function. A long-lived Windows process that decoded a few thousand modules ran the machine out of commit charge.🤖 Generated with Claude Code