From: Simon Strandgaard <0bz63fz3m1qt3001@...> Date: 2003-07-02T22:18:15+09:00 Subject: Re: rb_gc() and scan stack On Wed, 02 Jul 2003 22:17:41 +0900, Mauricio Fern�ndez wrote: > On Wed, Jul 02, 2003 at 07:52:17AM +0900, Simon Strandgaard wrote: >> I were experimenting with Init_stack, when I discovered a flaw in my mind. >> >> I thought that: local variables on stack would be marked in the >> mark-phase and therefore survive the sweep-phase. >> >> But my instance is being destroyed.. why ? >> >> Can someone enligthen me ? > [...] >> int main(int argc, char **argv) { >> ruby_init(); >> Init_dummy(); >> test(); >> return 0; >> } > > Could you please check if adding one stack frame in between works? > If it does, it'd mean it's exactly the same issue described in the links > I provided some time ago, that is, that ruby_init is capturing the > current SP to record the beginning of the stack, but you're storing > VALUEs in a stack frame above. > > Please test adding the following to your code: [snip] > > Cannot check now as my primary machine has no connection and the one > I'm writing from has no ruby... It doesn't help.. my main now looks like this: > expand -t4 main.c | tail -n12 void foo() { int a, b, c, d, e, f; /* just to take place in the stack */ a = b = c = d = e = f = 1; /* don't get warnings when -Wall */ test(); } int main(int argc, char **argv) { ruby_init(); Init_dummy(); foo(); return 0; } > Output is the same: > ./a.out alloc initialize 1 # free 2 ruby: [BUG] Segmentation fault ruby 1.8.0 (2003-06-23) [i386-freebsd5.0] Abort (core dumped) > I tried drawing on some paper, what is happening.. My initial drawing were wrong.. Now I understand. No problemo: The stack grows againts right. '.' = empty stack range (unkown to GC). 'R' = stack range scanned by GC. left-most-R == rb_gc_stack_end. right-most-R == rb_gc_stack_begin (set by Init_stack). '|' = current stack pointer. 'i' = where the instance is on the stack. --[ 0 ]----------------- top/hi [.....................] bottom/lo | --[ 1 ]----------------- entering ruby_init() top/hi [.....................] bottom/lo | --[ 2 ]----------------- leaving ruby_init() top/hi [RRRRR................] bottom/lo | --[ 3 ]----------------- entering Init_dummy() top/hi [RRRRR................] bottom/lo | --[ 4 ]----------------- leaving Init_dummy() top/hi [RRRRR................] bottom/lo | --[ 5 ]----------------- entering test() top/hi [RRRRR................] bottom/lo | --[ 6 ]----------------- instance = Dummy.new The instance is not within the mark-area, therefore it dies! top/hi [RRRRR..i.............] bottom/lo | --[ 7 ]----------------- rb_gc(); /* first time */ The instance is not within the RRRRR range... and Ruby is therefore unable to mark the instance. Thus it dies! top/hi [RRRRR................] bottom/lo | If we redo from step6 with Init_stack(begin).. with a lower begin address, then things will work. --[ 6a ]----------------- Init_stack(current_stack_ptr) top/hi [RRRRRRRR.............] bottom/lo | --[ 7a ]----------------- instance = Dummy.new This time the instance is within the area, and will thus survive top/hi [RRRRRRRR.............] bottom/lo | --[ 8a ]----------------- rb_gc(); /* first time: this time we survie */ top/hi [RRRRRRRR.............] bottom/lo | --[ 9a ]----------------- i = nil top/hi [RRRRRRRR.............] bottom/lo | --[ 10a ]----------------- rb_gc(); /* second time: this time we die */ top/hi [RRRRRRRR.............] bottom/lo | --[ 11a ]----------------- leaving test(); top/hi [RRRRRRRR.............] bottom/lo | -- Simon Strandgaard