From: nobuyoshi nakada Date: 2005-11-28T18:22:54+09:00 Subject: [ruby-dev:27856] Re: tail call and conservertive GC なかだです。 At Mon, 28 Nov 2005 16:44:31 +0900, Tanaka Akira wrote in [ruby-dev:27851]: > 調べてみると、 > > % ./miniruby -ve '10000.times { eval "" }' > ruby 1.9.0 (2005-11-28) [x86_64-linux] > *** glibc detected *** double free or corruption (fasttop): 0x00000000006d40c0 *** > > という問題まで絞りこめ、これはどうも rb_compile_string が > rb_parser_compile_string を tail call していて、 > 呼び出される前に VALUE volatile な vparser がスタック上から > 消えていて、GC されちゃっているということがわかりました。 rb_parser_compile_string()のvparserもvolatileなはずですが、そっ ちも消えてしまってるんでしょうか。 > (gdb) disassemble rb_compile_string > Dump of assembler code for function rb_compile_string: > 0x000000000045f7d0 : mov %rbx,0xffffffffffffffe8(%rsp) > 0x000000000045f7d5 : mov %r12,0xfffffffffffffff0(%rsp) > 0x000000000045f7da : mov %edx,%ebx > 0x000000000045f7dc : mov %r13,0xfffffffffffffff8(%rsp) > 0x000000000045f7e1 : sub $0x28,%rsp > 0x000000000045f7e5 : mov %rdi,%r13 > 0x000000000045f7e8 : mov %rsi,%r12 > 0x000000000045f7eb : callq 0x44f400 > 0x000000000045f7f0 : mov %rax,0x8(%rsp) > 0x000000000045f7f5 : mov 0x8(%rsp),%rdi > 0x000000000045f7fa : mov %ebx,%ecx > 0x000000000045f7fc : mov %r12,%rdx > 0x000000000045f7ff : mov %r13,%rsi > 0x000000000045f802 : mov 0x10(%rsp),%rbx > 0x000000000045f807 : mov 0x18(%rsp),%r12 > 0x000000000045f80c : mov 0x20(%rsp),%r13 > 0x000000000045f811 : add $0x28,%rsp > 0x000000000045f815 : jmpq 0x45f6e0 > End of assembler dump. なんとなく%rdi,%rsi,%edx,%ecxの順にレジスタ渡ししているっぽいで すが、vparser自体は渡されているんじゃないでしょうか。だとすれば 問題は、引数ではvolatileがついていてもメモリ上に置かれるとは限 らない、ということのような気がします。 > まぁ、tail call になるのを防止すればいいわけですが、tail > call になっているのはここに限らずかなりある感じです。 この推測が正しければ、volatileなローカル変数に保存しておくこと で解決しないでしょうか。 Index: node.h =================================================================== RCS file: /cvs/ruby/src/ruby/node.h,v retrieving revision 1.71 diff -U2 -p -r1.71 node.h --- node.h 8 Oct 2005 09:58:23 -0000 1.71 +++ node.h 28 Nov 2005 09:18:21 -0000 @@ -354,7 +354,7 @@ VALUE rb_parser_new(void); VALUE rb_parser_end_seen_p(VALUE); -NODE *rb_parser_compile_cstr(volatile VALUE, const char*, const char*, int, int); -NODE *rb_parser_compile_string(volatile VALUE, const char*, VALUE, int); -NODE *rb_parser_compile_file(volatile VALUE, const char*, VALUE, int); +NODE *rb_parser_compile_cstr(VALUE, const char*, const char*, int, int); +NODE *rb_parser_compile_string(VALUE, const char*, VALUE, int); +NODE *rb_parser_compile_file(VALUE, const char*, VALUE, int); NODE *rb_compile_cstr(const char*, const char*, int, int); Index: parse.y =================================================================== RCS file: /cvs/ruby/src/ruby/parse.y,v retrieving revision 1.425 diff -U2 -p -u -r1.425 parse.y --- parse.y 21 Nov 2005 13:51:48 -0000 1.425 +++ parse.y 28 Nov 2005 09:19:07 -0000 @@ -4643,7 +4643,8 @@ rb_compile_string(const char *f, VALUE s NODE* -rb_parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line) +rb_parser_compile_string(VALUE vparser, const char *f, VALUE s, int line) { struct parser_params *parser; + volatile VALUE self = vparser; Data_Get_Struct(vparser, struct parser_params, parser); @@ -4664,5 +4665,5 @@ rb_compile_cstr(const char *f, const cha NODE* -rb_parser_compile_cstr(volatile VALUE vparser, const char *f, const char *s, int len, int line) +rb_parser_compile_cstr(VALUE vparser, const char *f, const char *s, int len, int line) { return rb_parser_compile_string(vparser, f, rb_str_new(s, len), line); @@ -4684,7 +4685,8 @@ rb_compile_file(const char *f, VALUE fil NODE* -rb_parser_compile_file(volatile VALUE vparser, const char *f, VALUE file, int start) +rb_parser_compile_file(VALUE vparser, const char *f, VALUE file, int start) { struct parser_params *parser; + volatile VALUE self = vparser; Data_Get_Struct(vparser, struct parser_params, parser); -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦