Tietew です。

Railsを動かしていると表題のエラーが出て困っています。
環境は
・Debian sid (Linux 2.6.20, x86_64)
・glibc 2.6.1-1
・gcc 4.1.3 20070718 (prerelease) (Debian 4.1.2-14)
・Ruby 1.8 (SVN HEAD)
です。
# gdbで追いながらこのメール書いてます。

どこかで len=-1 な Bignum が生成されているっぽいです。
gdbで丹念に追ったところ、"%d" に 1 未満の Float を与えると再現し
ました。原因は rb_dbl2big か?

tietew@tomoyo:~$ ruby -ve 'p "%d" % 0.9'
ruby 1.8.6 (2007-08-07 patchlevel 5000) [x86_64-linux]
-e:1:in `%': negative allocation size (or too big) (NoMemoryError)

ちなみに i686 だと再現しません。

tietew@argon:~/ruby/ruby_1_8$ ruby -ve 'printf "%d\n", 0.9'
ruby 1.8.6 (2007-08-07 patchlevel 5000) [i686-linux]
0


追った過程です


** Rubyバックトレース
/usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/action_controller/benchmarking.rb:78:in `sprintf'
/usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/action_controller/benchmarking.rb:78:in `rendering_runtime'
/usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
  ... snip ...
/usr/local/bin/mongrel_rails:16

** gdbバックトレース
#0  rb_raise (exc=46939774505360,
    fmt=0x2ab103c91a80 "negative allocation size (or too big) (required %ld bytes)") at error.c:1058
#1  0x00002ab103c0ddf3 in ruby_xmalloc (size=-4) at gc.c:97
#2  0x00002ab103bd76f5 in bignew_1 (klass=46939774491280, len=-1, sign=1)
    at bignum.c:52
#3  0x00002ab103bd7743 in rb_big_clone (x=46939851488600) at bignum.c:63
#4  0x00002ab103bd8d2e in rb_big2str0 (x=46939851488600, base=10, trim=2)
    at bignum.c:691
#5  0x00002ab103bd8f89 in rb_big2str (x=46939851488600, base=10)
    at bignum.c:733
#6  0x00002ab103c76e4d in rb_f_sprintf (argc=2, argv=0x7fffa70f46a0)
    at sprintf.c:602
  ... snip ...

(gdb) f 3
#3  0x00002ab103bd7743 in rb_big_clone (x=46939851488600) at bignum.c:63
63          VALUE z = bignew_1(CLASS_OF(x), RBIGNUM(x)->len, RBIGNUM(x)->sign);
(gdb) l
58
59      VALUE
60      rb_big_clone(x)
61          VALUE x;
62      {
63          VALUE z = bignew_1(CLASS_OF(x), RBIGNUM(x)->len, RBIGNUM(x)->sign);
64
65          MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, RBIGNUM(x)->len);
66          return z;
67      }
(gdb) p *(unsigned long*)((unsigned char*)x)
$6 = 13
(gdb) p *(unsigned long*)((unsigned char*)x + 8)
$7 = 46939774491280
(gdb) p *(unsigned char*)((unsigned char*)x + 16)
$8 = 1 '\001'
(gdb) p *(long*)((unsigned char*)x + 24)
$9 = -1
(gdb) p ((unsigned char*)x + 32)
$10 = (unsigned char *) 0x2ab1092c7d78 "\020?Z\001"
(gdb) p rb_cBignum
$11 = 46939774491280

   # len=-1 になっている

(gdb) f 6
#6  0x00002ab103c76e4d in rb_f_sprintf (argc=2, argv=0x7fffa70f46a0)
    at sprintf.c:602
602                         tmp = rb_big2str(val, base);
(gdb) l
597                         s = nbuf;
598                         goto format_integer;
599                     }
600
601                     if (sign) {
602                         tmp = rb_big2str(val, base);
603                         s = RSTRING(tmp)->ptr;
604                         if (s[0] == '-') {
605                             s++;
606                             sc = '-';
(gdb) p val
$12 = 46939851488600
(gdb) p argv[0]
$14 = 46939851488760
(gdb) p argv[1]
$15 = 46939851488680

   # argv[1] != val

(gdb) p *(unsigned long*)((unsigned char*)argv[1] + 8)
$35 = 46939774494160
(gdb) p rb_cFloat
$38 = 46939774494160

   # Float

(gdb) p *(double*)((unsigned char*)argv[1] + 16)
$39 = 0.71855513799222548








-- 
Tietew <tietew / tietew.net>
Blog: http://www.tietew.jp/
PGP: 26CB 71BB B595 09C4 0153  81C4 773C 963A D51B 8CAA