From: ts Date: 2008-01-31T22:14:15+09:00 Subject: Re: Core team, I need your help >>>>> "J" == Jonas Pfenniger writes: J> You are right, I have joined the patch to this e-mail. Well, with this patch you reverse [ruby-cvs:17330] ruby_scope->local_vars[-1] is where ruby has stored ruby_scope in top_local_setup() when it don't have local variable. I'll try to explain it in another way Reverse (mentally) [ruby-cvs:17330] and look what do top_local_setup() * when it has no local variable if (ruby_scope->local_vars) { *vars++ = ruby_scope->local_vars[-1]; MEMCPY(vars, ruby_scope->local_vars, VALUE, i); rb_mem_clear(vars+i, len-i); } else { *vars++ = 0; rb_mem_clear(vars, len); } ruby_scope->local_vars = vars; ruby_scope->flags |= SCOPE_MALLOC; it will store 0 in *vars and put (vars + 1) in local_vars * now when the GC call obj_free() there is case T_SCOPE: if (RANY(obj)->as.scope.local_vars && RANY(obj)->as.scope.flags != SCOPE_ALLOCA) { VALUE *vars = RANY(obj)->as.scope.local_vars-1; if (!(RANY(obj)->as.scope.flags & SCOPE_CLONE) && vars[0] == 0) RUBY_CRITICAL(free(RANY(obj)->as.scope.local_tbl)); if (RANY(obj)->as.scope.flags & SCOPE_MALLOC) RUBY_CRITICAL(free(vars)); } break; the location vars[0] is the same than *vars in top_local_setup() and the GC will free RANY(obj)->as.scope.local_tbl Now apply the patch [ruby-cvs:17330] if (ruby_scope->local_vars) { *vars++ = ruby_scope->local_vars[-1]; MEMCPY(vars, ruby_scope->local_vars, VALUE, i); rb_mem_clear(vars+i, len-i); } else { *vars++ = (VALUE)ruby_scope; rb_mem_clear(vars, len); } ruby_scope->local_vars = vars; ruby_scope->flags |= SCOPE_MALLOC; this time it will store ruby_scope in *vars and it still put (vars + 1) in local_vars but the test in obj_free() is not modified and when the GC run it will not free scope.local_tbl because in obj_free() you have vars[0] == obj != 0 This is why you see a memory leak Guy Decoux