Actions
Bug #20585
closedSize of memory allocated by String.new(:capacity) is different from the specified value
Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 3.3.2 (2024-05-30 revision e5a195edf6) [x86_64-freebsd14.0]
Description
IMHO, if :capacity is specified in String.new, capa will be its value.
In fact, Ruby 3.2 seems to allocate the size as specified.
% cat string_capacity.rb
unless /\A3\.[23]\./ =~ RUBY_VERSION
raise NotImplementedError, 'Not Supported Ruby Version'
end
require 'inline'
class String
def super_inspect
self.class.superclass.instance_method(:inspect).bind(self).call
end
inline do |builder|
builder.include '<stdio.h>'
builder.add_compile_flags '-Wall'
builder.c_raw <<~CODE
VALUE capacity(int argc, VALUE *argv, VALUE self) {
struct RString *rstring = RSTRING(self);
if (! (RBASIC(self)->flags & RSTRING_NOEMBED)) {
return rb_to_symbol(rb_str_new_cstr("EMBED"));
} else {
if (RBASIC(self)->flags & ELTS_SHARED) {
return rb_to_symbol(rb_str_new_cstr("SHARED"));
} else {
return LONG2NUM(rstring->as.heap.aux.capa);
}
}
return Qnil; /* NOTREACHED */
}
CODE
end
end
% irb -I. -rstring_capacity
irb(main):001:0> [RUBY_PLATFORM, RUBY_VERSION]
=> ["x86_64-freebsd14.0", "3.2.4"]
irb(main):002:0> String.new('', capacity: 1024).capacity
=> 1024
irb(main):003:0> String.new('*'*1024, capacity: 1024).capacity
=> 1024
irb(main):004:0>
This is what I expect.
However, Ruby 3.3 seems to behave differently.
% irb -I. -rstring_capacity
irb(main):001> [RUBY_PLATFORM, RUBY_VERSION]
=> ["x86_64-freebsd14.0", "3.3.2"]
irb(main):002> String.new('', capacity: 1024).capacity
=> 1023
irb(main):003> String.new('*'*1024, capacity: 1024).capacity
=> 2047
irb(main):004>
- If only :capacity is specified, one byte less is allocated.
- If the initial string and its bytesize are specified, about twice the size is allocated.
Is this intentional?
Actions
Like0
Like0Like0Like0Like0Like0