$B<G$H?=$7$^$9!#(B
$B<!$N%5%s%W%k%3!<%I$r<B9T$9$k$H(B segv $B$rEG$-$^$9!#(B
$B3NG’$7$?(B Ruby $B=hM}7O$O(B ruby 1.9.3dev (2011-09-04 revision 33179)
[i686-linux] $B$G$9!#(B
#$B%5%s%W%k%3!<%I(B(#
StrClone = String.clone
Class.new(StrClone)
Marshal.dump(StrClone.new(“a”))
segv $B$rEG$/860x$O!"(BStrClone.new(“a”)
$B$G2u$l$?%%V%8%’%/%H(B($B%$%s%9%?%s%9JQ(B
$B?t$N?t$,$($i$$$3$H$K$J$C$F$k%%V%8%’%/%H(B)$B$r@8@.$7$F$$$k$?$a$G$9!#(B
Class.new(StrClone) $B$r<B9T$7$?;~E@$G(B StrClone
$B$NFC0[%/%i%9(B($B0J9_(B
$B$H=q$-$^$9(B)$B$,JQ99$5$l!"%a%=%C%I$N8!:w7k2L$,JQ$o$C$F$7$^$C$F$$(B
$B$^$9!#$3$N$?$a!"(BStrClone $B%$%s%9%?%s%9$N%"%m%1!<%?$,(B T_STRING
$B$N$b$N$+(B
$B$i!"(BT_OBJECT $B$N$b$N$H$J$j!"(BStrClone.new $B$G(B T_OBJECT
$B$N%*%V%8%’%/%H$,3d$j(B
$BEv$F$i$l$^$9!#(B
$B$7$+$7!"(BStrClone
$B$N%a%=%C%I%F!<%V%k$OJQ99$5$l$F$$$J$$$?$a!“3d$jEv$F$?%(B
$B%V%8%’%/%H$KBP$7$F$OJ8;zNs$N%$%K%7%c%i%$%6$,8F$S=P$5$l$^$9!#$3$N$;$$$G!"(B
T_OBJECT
$B$N%%V%8%’%/%H$KBP$7$FJ8;zNs$N=i4|2==hM}$,Av$C$F$7$^$$!“2u$l$?(B
$B%%V%8%’%/%H$,:n$i$l$^$9!#%5%s%W%k%3!<%I$G$O!"$3$N!"2u$l$?%%V%8%’%/%H$r(B
Marshal.dump
$B$GEG$3$&$H$7$?$H$-$K!”%$%s%9%?%s%9JQ?t$N%@%s%W$r$7$h$&$H$7(B
$B$F!”(Bsegv $B$rEG$-$^$9!#(B
class $B%*%V%8%’%/%H$N(B clone
$B$d!“FC0[%/%i%9$N=hM}$OJ#;($J$N$GM}2r$7$-$l$F(B
$B$$$^$;$s$,!”:#2s$N>l9g!"(BStrClone
$B$NFC0[%/%i%9$,JQ99$5$l$F$7$^$&$N$,LdBj(B
$B$K8+$($^$9!#(BStrClone
$B$NFC0[%a%=%C%I$,JQ99$5$l$F$7$^$&$3$H$N860x$O!“0J2<(B
$B$N$h$&$K!”(Bmake_metaclass(class.c) $B$K$"$j$^$9!#(B
#define ENSURE_EIGENCLASS(klass)
(rb_ivar_get(METACLASS_OF(klass), id_attached) == (klass) ?
METACLASS_OF(klass) : make_metaclass(klass))
static inline VALUE
make_metaclass(VALUE klass)
{
…
super = RCLASS_SUPER(klass);
while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super);
RCLASS_SUPER(metaclass) = super ? ENSURE_EIGENCLASS(super) :
rb_cClass;
....
return metaclass;
}
$B$3$3$N(B ENSURE_EIGENCLASS $B$H$$$&%^%/%m$O!"(Bklass $B$,(B StrClone
$B$@$C$?>l9g$K(B
rb_ivar_get(METACLASS_OF(StrClone), id_attached) == (StrClone)
$B$NH=Dj$,56$K$J$j!"(Bmake_metaclass(StrClone) $B$,<B9T$5$l$^$9!#(B
$B$3$N(B make_metaclass(StrClone) $B$G!"(BStrClone
$B$NFC0[%/%i%9$,JQ99$5$l$^$9!#(B
$B$3$l$,2?8N5/$3$k$+$H$$$&$H!"(B $B$N(B “attached”
$B$H$$$&%$%s%9%?(B
$B%s%9JQ?t$,!"(BStrClone $B$r;X$7$F$$$J$$$?$a$G$9!#(B $B$N(B
“attached”
$B$O!"(Brb_singleton_class_clone(class.c)$B$N0J2<$N=hM}$K$h$C(B
$B$F!"<+J,<+?H$r;X$7$F$$$^$9!#$3$NItJ,$r>/$7$+$($F!"(B $B$N(B
“attached” $B$,(B StrClone $B$r;X$9$h$&$K$9$l$P!"(BStrClone
$B$NFC0[%/%i%9$,JQ(B
$B99$5$l$F$7$^$&$H$$$&E@$K$D$$$F$O2r7h$G$-$^$9!#(B
VALUE
rb_singleton_class_clone(VALUE obj)
{
VALUE klass = RBASIC(obj)->klass;
...
VALUE clone = class_alloc((RBASIC(klass)->flags & ~(FL_MARK)),
0);
if (BUILTIN_TYPE(obj) == T_CLASS) {
RBASIC(clone)->klass = (VALUE)clone; /* <= $B%3%3$rDL$k(B(1)
*/
}
else {
RBASIC(clone)->klass = rb_singleton_class_clone(klass);
}
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
/* (1) $B$rDL$C$?>l9g!"(BRBASIC(clone)->klass = clone */
/* clone $B$N(B "__attached__" $B$O(B clone $B<+?H$r;X$9(B */
...
}
$BK%a!<%k$NKvHx$K!"(Brb_singleton_class_clone $B$J$I$N(B “attached”
$B$N=hM}(B
$B$KBP$9$k%Q%C%A$rE:IU$7$^$9!#FC0[%/%i%9$,>o$K(B “attached”
$B$K2?$+$7$i$r(B
$B;X$7$F$$$kI,MW$,$"$k$N$J$i!"(Bclass.c
$B$KBP$9$k%Q%C%A$OL5;k$7$F$/$@$5$$!#(B
$BFC0[%/%i%9$N(B “attached”
$B$,<+J,<+?H$r;X$7$F$$$J$$$H$^$:$$%1!<%9$,$"$k(B
$B$+$I$&$+$,J,$+$i$J$$$N$G!"$3$N%Q%C%A$,M-8z$+$I$&$+$OJ,$+$j$^$;$s$,!":F8=(B
$B4D6-$G%5%s%W%k%3!<%I$rL5;v<B9T$7!"(Btest-all
$B$K$bDL2a$9$k$3$H$O3NG’$G$-$^(B
$B$7$?!#(B
$B;29M$K$7$F$$$?$@$1$l$P9,$$$G$9!#(B
$B$h$m$7$/$*4j$$$$$?$7$^$9!#(B
$B%Q%C%A(B
Index: object.c
— object.c (revision 33182)
+++ object.c (working copy)
@@ -272,12 +272,17 @@
rb_obj_clone(VALUE obj)
{
VALUE clone;
-
VALUE singleton;
if (rb_special_const_p(obj)) {
rb_raise(rb_eTypeError, “can’t clone %s”,
rb_obj_classname(obj));
}
clone = rb_obj_alloc(rb_obj_class(obj));
- RBASIC(clone)->klass = rb_singleton_class_clone(obj);
- singleton = rb_singleton_class_clone(obj);
- RBASIC(clone)->klass = singleton;
- if (FL_TEST(singleton, FL_SINGLETON)) {
-
rb_singleton_class_attached(singleton, clone);
- }
RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone,
FL_TAINT) | FL_TEST(clone, FL_UNTRUSTED)) &
~(FL_FREEZE|FL_FINALIZE|FL_MARK);
init_copy(clone, obj);
rb_funcall(clone, id_init_clone, 1, obj);
Index: class.c
===================================================================
— class.c (revision 33182)
+++ class.c (working copy)
@@ -230,12 +230,15 @@
struct clone_method_data data;
/* copy singleton(unnamed) class */
VALUE clone = class_alloc((RBASIC(klass)->flags & ~(FL_MARK)),
0); -
int attach; if (BUILTIN_TYPE(obj) == T_CLASS) { RBASIC(clone)->klass = (VALUE)clone;
-
attach = 0; } else { RBASIC(clone)->klass = rb_singleton_class_clone(klass);
-
attach = 1; } RCLASS_SUPER(clone) = RCLASS_SUPER(klass);
@@ -251,7 +254,9 @@
data.klass = (VALUE)clone;
st_foreach(RCLASS_M_TBL(klass), clone_method,
(st_data_t)&data);
-
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
-
if (attach) {
-
rb_singleton_class_attached(RBASIC(clone)->klass,
(VALUE)clone);
-
}} FL_SET(clone, FL_SINGLETON); return (VALUE)clone;