Skip to content

Conversation

@byroot
Copy link
Member

@byroot byroot commented Feb 1, 2026

Context

Ruby internals have had a ruby_sized_xfree function for a very longtime. Until recently it was just used to feed the freed size into the GC statistics, to allow it to be smarter as of when to trigger.

However C23 does introduce free_sized: https://en.cppreference.com/w/c/memory/free_sized.html, which when used allow allocator to either deallocate faster or be more secure by aborting when the size doesn't match.

It is however important to note that passing an incorrect size is undefined behavior, so the allocator could just as well leak or crash.

Very recently glibc 2.43 added support for free_sized: https://sourceware.org/pipermail/libc-announce/2026/000052.html, and other common allocators like jemalloc have supported it for years.
However if the allocator doesn't support it, it's easily shimed with a simple macro that discard the size.

The last few days I've changed a majority of xfree calls inside MRI to use ruby_sized_xfree, and added some debug checks inside it to ensure the passed size is correct, and that surfaced a few minor bugs (mostly strings losing a few bytes of capacity when switching between encodings). (e.g. ruby/ruby#16010)

Now most of Ruby's own codebase have been converted, and most of the remaining unsized frees are within prism and similarly vendored codebases. I haven't yet hooked MRI to the allocator, for now it's still only used for GC statistics.

xrealloc_sized

I'm not sure why, but C23 standard doesn't defined realloc_sized, but similarly Ruby had ruby_sized_xrealloc for a while, and I think it does make a lot of sense for that purpose given realloc is essentially malloc + free.

Proposal

I'd like to also convert Prism to use sized frees as well, so that when compiled inside Ruby it can use ruby_sized_xfree, hence play better with the GC and potentially benefit from C23 free_sized performance benefits in the future.

In this PR I implemented debug checks for the allocator sizes, and converted a few call sites to the new API, as well as added a couple convenience macros that make using free_sized much easier.

A side benefit of these debug checks is that if you accidentally use raw free or raw malloc, it will blow up.

If there is interest from the maintainers, I can convert the rest of the prism codebase.

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.

2 participants