Project

General

Profile

Actions

Bug #20614

open

Integer#size returns incorrect values on 64-bit Windows

Added by surusek (Łukasz Sur) 5 days ago. Updated 4 days ago.

Status:
Open
Assignee:
-
Target version:
-
ruby -v:
ruby 3.4.0dev (2024-07-08T11:00:01Z master 02c4f0c89d [x64-mswin64_140]
[ruby-core:118483]

Description

According to the ruby/spec, 0.size should return size of the machine word in bytes, but on x64-mswin64_140 (both release 3.3.3 and git revision 02c4f0c89d) it doesn't. Following example:

a, b = 0.size, [0].pack('J').length
puts a, b

should print two 8s, but on x64-mswin64_140, a is 4.
Issue is most likely caused by use of long instead of SIGNED_VALUE in internal/fixnum.h and fix_size function in numeric.c, because on Windows, long is always a 32-bit number.

Updated by akr (Akira Tanaka) 5 days ago

You can use RbConfig::SIZEOF to query the size of a C type.

% ruby -v -rrbconfig/sizeof -e 'pp RbConfig::SIZEOF'
ruby 3.4.0dev (2024-05-16T19:35:22Z master 854cbbd5a9) [x86_64-linux]
{"int"=>4,
 "short"=>2,
 "long"=>8,
 "long long"=>8,
 "__int128"=>16,
 "off_t"=>8,
 "void*"=>8,
 "float"=>4,
 "double"=>8,
 "time_t"=>8,
 "clock_t"=>8,
 "size_t"=>8,
 "ptrdiff_t"=>8,
 "dev_t"=>8,
 "int8_t"=>1,
 "uint8_t"=>1,
 "int16_t"=>2,
 "uint16_t"=>2,
 "int32_t"=>4,
 "uint32_t"=>4,
 "int64_t"=>8,
 "uint64_t"=>8,
 "int128_t"=>16,
 "uint128_t"=>16,
 "intptr_t"=>8,
 "uintptr_t"=>8,
 "ssize_t"=>8,
 "int_least8_t"=>1,
 "int_least16_t"=>2,
 "int_least32_t"=>4,
 "int_least64_t"=>8,
 "int_fast8_t"=>1,
 "int_fast16_t"=>8,
 "int_fast32_t"=>8,
 "int_fast64_t"=>8,
 "intmax_t"=>8,
 "sig_atomic_t"=>4,
 "wchar_t"=>4,
 "wint_t"=>4,
 "wctrans_t"=>8,
 "wctype_t"=>8,
 "_Bool"=>1,
 "long double"=>16,
 "float _Complex"=>8,
 "double _Complex"=>16,
 "long double _Complex"=>32,
 "__float128"=>16,
 "_Decimal32"=>4,
 "_Decimal64"=>8,
 "_Decimal128"=>16,
 "__float80"=>16}

Updated by alanwu (Alan Wu) 5 days ago · Edited

IMO based on the current wording of the documentation it should always return sizeof(VALUE) for fixnums, because VALUE holds the machine representation for fixnums.

By the way, ruby/spec is not a specification for how things ought to behave; it's descriptive not prescriptive. Check out the README of the project: https://github.com/ruby/spec?tab=readme-ov-file#description-and-motivation

Updated by Eregon (Benoit Daloze) 4 days ago

Agreed with @alanwu (Alan Wu), the docs seems clear, and one would expect this method returns how many bytes are used to represent the Integer (not counting object header overhead for bignums, fair enough):

  int.size  ->  int

Document-method: Integer#size

Returns the number of bytes in the machine representation of int
(machine dependent).

  1.size               #=> 8
  -1.size              #=> 8
  2147483647.size      #=> 8
  (256**10 - 1).size   #=> 10
  (256**20 - 1).size   #=> 20
  (256**40 - 1).size   #=> 40

So it should be pointer-size bytes for any Fixnum on any platform (since Fixnum are tagged pointers).

Actions

Also available in: Atom PDF

Like0
Like1Like0Like1