Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Analyse Valgrind report #104

Closed
mudge opened this issue Sep 21, 2023 · 11 comments
Closed

Analyse Valgrind report #104

mudge opened this issue Sep 21, 2023 · 11 comments

Comments

@mudge
Copy link
Owner

mudge commented Sep 21, 2023

Running ruby_memcheck has produced the following possible leaks from Valgrind:

16 bytes in 1 blocks are definitely lost in loss record 5,435 of 30,516
  operator new(unsigned long, std::nothrow_t const&) (vg_replace_malloc.c:592)
 *re2_regexp_scan(unsigned long, unsigned long) (re2.cc:1351)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:820)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  yield_under (vm_eval.c:1983)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2383)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  rb_ec_exec_node (eval.c:289)
  ruby_run_node (eval.c:330)
  rb_main (main.c:38)
  main (main.c:57)

32 bytes in 1 blocks are definitely lost in loss record 11,893 of 30,516
  operator new(unsigned long) (vg_replace_malloc.c:472)
 *re2::RE2::Init(std::basic_string_view<char, std::char_traits<char> >, re2::RE2::Options const&) (at /home/mudge/re2/lib/re2.so)
 *re2::RE2::RE2(char const*) (at /home/mudge/re2/lib/re2.so)
 *re2_GlobalReplace(unsigned long, unsigned long, unsigned long, unsigned long) (re2.cc:1439)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:820)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  yield_under (vm_eval.c:1983)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2383)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  rb_ec_exec_node (eval.c:289)
  ruby_run_node (eval.c:330)
  rb_main (main.c:38)
  main (main.c:57)

32 bytes in 1 blocks are definitely lost in loss record 11,894 of 30,516
  operator new(unsigned long) (vg_replace_malloc.c:472)
 *re2::RE2::Init(std::basic_string_view<char, std::char_traits<char> >, re2::RE2::Options const&) (at /home/mudge/re2/lib/re2.so)
 *re2::RE2::RE2(char const*) (at /home/mudge/re2/lib/re2.so)
 *re2_Replace(unsigned long, unsigned long, unsigned long, unsigned long) (re2.cc:1400)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:820)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  yield_under (vm_eval.c:1983)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2383)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  rb_ec_exec_node (eval.c:289)
  ruby_run_node (eval.c:330)
  rb_main (main.c:38)
  main (main.c:57)

32 bytes in 2 blocks are definitely lost in loss record 11,906 of 30,516
  operator new(unsigned long, std::nothrow_t const&) (vg_replace_malloc.c:592)
 *re2_regexp_scan(unsigned long, unsigned long) (re2.cc:1351)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:820)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  yield_under (vm_eval.c:1983)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  rb_vm_call0 (vm_eval.c:58)
  rb_vm_call_kw (vm_eval.c:303)
  vm_yield_with_cfunc (vm_insnhelper.c:4288)
  vm_invoke_ifunc_block (vm_insnhelper.c:4438)
  vm_invoke_block (vm_insnhelper.c:4493)
  vm_invokeblock_i (vm_insnhelper.c:5008)
  vm_sendish (vm_insnhelper.c:5088)
  vm_exec_core (insns.def:941)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  yield_under (vm_eval.c:1983)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2383)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  rb_ec_exec_node (eval.c:289)
  ruby_run_node (eval.c:330)
  rb_main (main.c:38)
  main (main.c:57)

40 bytes in 1 blocks are definitely lost in loss record 12,409 of 30,516
  operator new(unsigned long) (vg_replace_malloc.c:472)
 *re2::Regexp::ParseState::PushLiteral(int) (at /home/mudge/re2/lib/re2.so)
 *re2::Regexp::Parse(std::basic_string_view<char, std::char_traits<char> >, re2::Regexp::ParseFlags, re2::RegexpStatus*) (at /home/mudge/re2/lib/re2.so)
 *re2::RE2::Init(std::basic_string_view<char, std::char_traits<char> >, re2::RE2::Options const&) (at /home/mudge/re2/lib/re2.so)
 *re2::RE2::RE2(char const*) (at /home/mudge/re2/lib/re2.so)
 *re2_GlobalReplace(unsigned long, unsigned long, unsigned long, unsigned long) (re2.cc:1439)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:820)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  yield_under (vm_eval.c:1983)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2383)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  rb_ec_exec_node (eval.c:289)
  ruby_run_node (eval.c:330)
  rb_main (main.c:38)
  main (main.c:57)

71 bytes in 1 blocks are definitely lost in loss record 18,497 of 30,516
  operator new(unsigned long) (vg_replace_malloc.c:472)
  std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_mutate(unsigned long, unsigned long, char const*, unsigned long) (at /usr/lib/aarch64-linux-gnu/libstdc++.so.6.0.30)
  std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long) (at /usr/lib/aarch64-linux-gnu/libstdc++.so.6.0.30)
 *re2::RegexpStatus::Text[abi:cxx11]() const (at /home/mudge/re2/lib/re2.so)
 *re2::RE2::Set::Add(std::basic_string_view<char, std::char_traits<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) (at /home/mudge/re2/lib/re2.so)
 *re2_set_add(unsigned long, unsigned long) (re2.cc:1570)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:820)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  yield_under (vm_eval.c:1983)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2383)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  rb_ec_exec_node (eval.c:289)
  ruby_run_node (eval.c:330)
  rb_main (main.c:38)
  main (main.c:57)

72 (40 direct, 32 indirect) bytes in 1 blocks are definitely lost in loss record 18,991 of 30,516
  operator new(unsigned long) (vg_replace_malloc.c:472)
 *re2::Regexp::ParseState::PushLiteral(int) (at /home/mudge/re2/lib/re2.so)
 *re2::Regexp::Parse(std::basic_string_view<char, std::char_traits<char> >, re2::Regexp::ParseFlags, re2::RegexpStatus*) (at /home/mudge/re2/lib/re2.so)
 *re2::RE2::Init(std::basic_string_view<char, std::char_traits<char> >, re2::RE2::Options const&) (at /home/mudge/re2/lib/re2.so)
 *re2::RE2::RE2(char const*) (at /home/mudge/re2/lib/re2.so)
 *re2_Replace(unsigned long, unsigned long, unsigned long, unsigned long) (re2.cc:1400)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:820)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  yield_under (vm_eval.c:1983)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2383)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  rb_ec_exec_node (eval.c:289)
  ruby_run_node (eval.c:330)
  rb_main (main.c:38)
  main (main.c:57)

152 bytes in 1 blocks are definitely lost in loss record 22,512 of 30,516
  operator new(unsigned long, std::nothrow_t const&) (vg_replace_malloc.c:592)
 *re2_regexp_initialize(int, unsigned long*, unsigned long) (re2.cc:796)
  vm_call0_cfunc_with_frame (vm_eval.c:150)
  vm_call0_cfunc (vm_eval.c:164)
  vm_call0_body (vm_eval.c:210)
  vm_call0_cc (vm_eval.c:87)
  rb_call0 (vm_eval.c:551)
  rb_class_new_instance_pass_kw (object.c:2021)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:820)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  yield_under (vm_eval.c:1983)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2383)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  rb_ec_exec_node (eval.c:289)
  ruby_run_node (eval.c:330)
  rb_main (main.c:38)
  main (main.c:57)

506 (432 direct, 74 indirect) bytes in 1 blocks are definitely lost in loss record 26,718 of 30,516
  operator new(unsigned long) (vg_replace_malloc.c:472)
 *re2::Compiler::Compiler() (at /home/mudge/re2/lib/re2.so)
 *re2::Compiler::Compile(re2::Regexp*, bool, long) (at /home/mudge/re2/lib/re2.so)
 *re2::Regexp::CompileToProg(long) (at /home/mudge/re2/lib/re2.so)
 *re2::RE2::Init(std::basic_string_view<char, std::char_traits<char> >, re2::RE2::Options const&) (at /home/mudge/re2/lib/re2.so)
 *re2::RE2::RE2(char const*) (at /home/mudge/re2/lib/re2.so)
 *re2_GlobalReplace(unsigned long, unsigned long, unsigned long, unsigned long) (re2.cc:1439)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:820)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  yield_under (vm_eval.c:1983)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2383)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  rb_ec_exec_node (eval.c:289)
  ruby_run_node (eval.c:330)
  rb_main (main.c:38)
  main (main.c:57)

528 (432 direct, 96 indirect) bytes in 1 blocks are definitely lost in loss record 27,033 of 30,516
  operator new(unsigned long) (vg_replace_malloc.c:472)
 *re2::Compiler::Compiler() (at /home/mudge/re2/lib/re2.so)
 *re2::Compiler::Compile(re2::Regexp*, bool, long) (at /home/mudge/re2/lib/re2.so)
 *re2::Regexp::CompileToProg(long) (at /home/mudge/re2/lib/re2.so)
 *re2::RE2::Init(std::basic_string_view<char, std::char_traits<char> >, re2::RE2::Options const&) (at /home/mudge/re2/lib/re2.so)
 *re2::RE2::RE2(char const*) (at /home/mudge/re2/lib/re2.so)
 *re2_Replace(unsigned long, unsigned long, unsigned long, unsigned long) (re2.cc:1400)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:820)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  yield_under (vm_eval.c:1983)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2383)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  invoke_block (vm.c:1398)
  invoke_iseq_block_from_c (vm.c:1454)
  invoke_block_from_c_bh (vm.c:1472)
  vm_yield_with_cref (vm.c:1509)
  vm_yield (vm.c:1517)
  rb_yield_0 (vm_eval.c:1348)
  rb_yield (vm_eval.c:1364)
  rb_ary_collect (array.c:3834)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3268)
  vm_sendish.constprop.0 (vm_insnhelper.c:5080)
  vm_exec_core (insns.def:801)
  rb_vm_exec (vm.c:2374)
  rb_ec_exec_node (eval.c:289)
  ruby_run_node (eval.c:330)
  rb_main (main.c:38)
  main (main.c:57)
@stanhu
Copy link
Collaborator

stanhu commented Sep 21, 2023

I remember doing this analysis a few months ago. I think the ones inre2::RE2::Init() are false positives. The first one was the most intriguing one, but I thought re2_scanner_free() should have handled that.

@mudge
Copy link
Owner Author

mudge commented Sep 21, 2023

There’s a few involving StringPieces (now absl::string_views) which makes me wonder if there are some lifetime issues where the view is outliving the string or vice versa. I definitely want to take another look at how a Scanner contains a pointer to a StringPiece…

@mudge
Copy link
Owner Author

mudge commented Sep 22, 2023

@peterzhu2118 suggested the source of the Scanner leak in rewind where I overwrite the input without deleting the old: https://ruby.social/@peterzhu2118/111108837791465609

@stanhu
Copy link
Collaborator

stanhu commented Sep 22, 2023

Oh, right, that makes sense.

@mudge
Copy link
Owner Author

mudge commented Sep 22, 2023

Following @peterzhu2118's advice, I've been trying to focus on minimal test cases that trigger the Valgrind reports: for the leak in re2_regexp_initialize, it only occurs in the following example (all the other examples for that method return no leaks):

    it "raises an error if given an inappropriate type" do
      expect { RE2::Regexp.new(nil) }.to raise_error(TypeError)
    end

@mudge
Copy link
Owner Author

mudge commented Sep 22, 2023

It seems to be fixed by adding a StringValue(pattern) earlier in the function before creating any RE2::Options or RE2 objects (presumably the previous calls to StringValuePtr were raising an exception after things had been allocated, causing them to never be freed).

@mudge
Copy link
Owner Author

mudge commented Sep 22, 2023

This one has me currently stumped: re2_set_add leaks if and only if you hit this branch:

re2/ext/re2/re2.cc

Lines 1571 to 1573 in 23fab86

if (index < 0) {
rb_raise(rb_eArgError, "str rejected by RE2::Set->Add(): %s", err.c_str());
}

@stanhu
Copy link
Collaborator

stanhu commented Sep 22, 2023

My valgrind trace shows:

71 bytes in 1 blocks are definitely lost in loss record 18,062 of 30,701
  operator new(unsigned long) (at /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
  std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_mutate(unsigned long, unsigned long, char const*, unsigned long) (at /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
  std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long) (at /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
 *re2::RegexpStatus::Text[abi:cxx11]() const (regexp.cc:538)
 *re2::RE2::Set::Add(std::basic_string_view<char, std::char_traits<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) (set.cc:65)
 *re2_set_add(unsigned long, unsigned long) (re2.cc:1572)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3037)
  vm_call_method_each_type (vm_insnhelper.c:3639)
  vm_call_method (vm_insnhelper.c:3750)
  vm_sendish (vm_insnhelper.c:4751)
  vm_exec_core (insns.def:778)
  rb_vm_exec (vm.c:2211)
  invoke_block (vm.c:1316)
  invoke_iseq_block_from_c (vm.c:1372)
  invoke_block_from_c_bh (vm.c:1390)
  vm_yield_with_cref (vm.c:1427)
  yield_under (vm_eval.c:1969)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3037)
  vm_call_method_each_type (vm_insnhelper.c:3639)
  vm_call_method (vm_insnhelper.c:3750)
  vm_sendish (vm_insnhelper.c:4751)
  vm_exec_core (insns.def:759)
  rb_vm_exec (vm.c:2220)
  invoke_block (vm.c:1316)
  invoke_iseq_block_from_c (vm.c:1372)
  invoke_block_from_c_bh (vm.c:1390)
  vm_yield_with_cref (vm.c:1427)
  vm_yield (vm.c:1435)
  rb_yield_0 (vm_eval.c:1347)
  rb_yield (vm_eval.c:1363)
  rb_ary_collect (array.c:3564)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3037)
  vm_sendish (vm_insnhelper.c:4751)
  vm_exec_core (insns.def:759)
  rb_vm_exec (vm.c:2211)
  invoke_block (vm.c:1316)
  invoke_iseq_block_from_c (vm.c:1372)
  invoke_block_from_c_bh (vm.c:1390)
  vm_yield_with_cref (vm.c:1427)
  vm_yield (vm.c:1435)
  rb_yield_0 (vm_eval.c:1347)
  rb_yield (vm_eval.c:1363)
  rb_ary_collect (array.c:3564)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3037)
  vm_sendish (vm_insnhelper.c:4751)
  vm_exec_core (insns.def:759)
  rb_vm_exec (vm.c:2211)
  invoke_block (vm.c:1316)
  invoke_iseq_block_from_c (vm.c:1372)
  invoke_block_from_c_bh (vm.c:1390)
  vm_yield_with_cref (vm.c:1427)
  vm_yield (vm.c:1435)
  rb_yield_0 (vm_eval.c:1347)
  rb_yield (vm_eval.c:1363)
  rb_ary_collect (array.c:3564)
  vm_call_cfunc_with_frame (vm_insnhelper.c:3037)
  vm_sendish (vm_insnhelper.c:4751)
  vm_exec_core (insns.def:759)
  rb_vm_exec (vm.c:2211)
  rb_ec_exec_node (eval.c:280)
  ruby_run_node (eval.c:321)
  main (main.c:47)

Is valgrind flagging s.append(": "); in https://github.com/google/re2/blob/09de536bb7c77c2e0869a001f012d49560f56cbe/re2/regexp.cc#L538? This feels like a false positive.

I applied this diff to see the symbols in abseil and libre2:

diff --git a/ext/re2/extconf.rb b/ext/re2/extconf.rb
index f8fd706..c8c6681 100644
--- a/ext/re2/extconf.rb
+++ b/ext/re2/extconf.rb
@@ -119,8 +119,8 @@ end

 def build_extension(static_p = false)
   # Enable optional warnings but disable deprecated register warning for Ruby 2.6 support
-  $CFLAGS << " -Wall -Wextra -funroll-loops"
-  $CPPFLAGS << " -Wno-register"
+  $CFLAGS << " -Wall -Wextra -funroll-loops -ggdb3"
+  $CPPFLAGS << " -Wno-register -ggdb3"

   # Pass -x c++ to force gcc to compile the test program
   # as C++ (as it will end in .c by default).
@@ -395,11 +395,11 @@ def build_with_vendored_libraries
   abseil_recipe, re2_recipe = load_recipes

   process_recipe(abseil_recipe) do |recipe|
-    recipe.configure_options += ['-DABSL_PROPAGATE_CXX_STD=ON', '-DCMAKE_CXX_VISIBILITY_PRESET=hidden']
+    recipe.configure_options += ['-DABSL_PROPAGATE_CXX_STD=ON', '-DCMAKE_CXX_VISIBILITY_PRESET=hidden', '-DCMAKE_CXXFLAGS=-ggdb3']
   end

   process_recipe(re2_recipe) do |recipe|
-    recipe.configure_options += ["-DCMAKE_PREFIX_PATH=#{abseil_recipe.path}", '-DCMAKE_CXX_FLAGS=-DNDEBUG',
+    recipe.configure_options += ["-DCMAKE_PREFIX_PATH=#{abseil_recipe.path}", '-DCMAKE_CXX_FLAGS=-DNDEBUG', '-DCMAKE_CXX_FLAGS=-ggdb3',
                                  '-DCMAKE_CXX_VISIBILITY_PRESET=hidden']
   end

@mudge
Copy link
Owner Author

mudge commented Sep 22, 2023

I've been talking to Peter on ruby.social about this while I look into it: https://ruby.social/@mudge/111110365227989022

In short, the leak disappears if I remove the err string and stop passing it to Add() but that doesn't seem right.

@stanhu
Copy link
Collaborator

stanhu commented Sep 22, 2023

As https://valgrind.org/docs/manual/faq.html#faq.reports mentions:

Many implementations of the C++ standard libraries use their own memory pool allocators. Memory for quite a number of destructed objects is not immediately freed and given back to the OS, but kept in the pool(s) for later re-use. The fact that the pools are not freed at the exit of the program cause Valgrind to report this memory as still reachable. The behaviour not to free pools at the exit could be called a bug of the library though.

I tried to make valgrind run with GLIBCXX_FORCE_NEW yet, but so far that hasn't helped.

mudge added a commit that referenced this issue Sep 22, 2023
See #104

Specifically, ensure we delete the previous input inside an RE2::Scanner
before replacing it and check whether inputs are strings as early as
possible to avoid raising an exception after allocating memory.
mudge added a commit that referenced this issue Sep 22, 2023
See #104

When we raise an exception in re2_set_add, the memory used by the
std::string used to store the error message is never freed so we need to
free it ourselves manually. However, we also need a copy of what is
inside it to return to the user so we turn that into a C string first.
The maximum message size of 100 is taken from the length of the prefix
of the message (33 characters) and the longest error message currently
in RE2 (35 characters) plus a little extra in case new releases of RE2
add longer messages.
@mudge
Copy link
Owner Author

mudge commented Sep 22, 2023

I think I've now fixed all the leaks in this report in #105

mudge added a commit that referenced this issue Sep 22, 2023
See #104

Specifically, ensure we delete the previous input inside an RE2::Scanner
before replacing it and check whether inputs are strings as early as
possible to avoid raising an exception after allocating memory.

Thanks to @peterzhu2118 for both authoring ruby_memcheck and helping
find the source of these leaks.
mudge added a commit that referenced this issue Sep 22, 2023
See #104

When we raise an exception in re2_set_add, the memory used by the
std::string used to store the error message is never freed so we need to
free it ourselves manually. However, we also need a copy of what is
inside it to return to the user so we turn that into a C string first.
The maximum message size of 100 is taken from the length of the prefix
of the message (33 characters) and the longest error message currently
in RE2 (35 characters) plus a little extra in case new releases of RE2
add longer messages.

Thanks to @peterzhu2118 for both authoring ruby_memcheck and helping
find the source of these leaks.
mudge added a commit that referenced this issue Sep 22, 2023
See #104

When we raise an exception in re2_set_add, the memory used by the
std::string used to store the error message is never freed so we need to
free it ourselves manually. However, we also need a copy of what is
inside it to return to the user so we turn that into a C string first.
The maximum message size of 100 is taken from the length of the prefix
of the message (33 characters) and the longest error message currently
in RE2 (35 characters) plus a little extra in case new releases of RE2
add longer messages.

Thanks to @peterzhu2118 for both authoring ruby_memcheck and helping
find the source of these leaks.
mudge added a commit that referenced this issue Sep 22, 2023
See #104

When we raise an exception in re2_set_add, the memory used by the
std::string used to store the error message is never freed so we need to
free it ourselves manually. However, we also need a copy of what is
inside it to return to the user so we turn that into a C string first.
The maximum message size of 100 is taken from the length of the prefix
of the message (33 characters) and the longest error message currently
in RE2 (35 characters) plus a little extra in case new releases of RE2
add longer messages.

Thanks to @peterzhu2118 for both authoring ruby_memcheck and helping
find the source of these leaks.
mudge added a commit that referenced this issue Sep 22, 2023
See #104

When we raise an exception in re2_set_add, the memory used by the
std::string used to store the error message is never freed. Fix this by
ensuring it goes out of scope before we call rb_raise.

However, we also need a copy of what is inside it to return to the user
so we take a copy of its contents as a C string first. The current
longest error message inside RE2 is 35 characters long so 100 characters
gives us some headroom in case new releases of RE2 add longer messages.

Thanks to @peterzhu2118 for both authoring ruby_memcheck and helping
find the source of these leaks.
mudge added a commit that referenced this issue Sep 22, 2023
See #104

When we raise an exception in re2_set_add, the memory used by the
std::string used to store the error message is never freed. Fix this by
ensuring it goes out of scope before we call rb_raise.

However, we also need a copy of what is inside it to return to the user
so we take a copy of its contents as a C string first. The current
longest error message inside RE2 is 35 characters long so 100 characters
gives us some headroom in case new releases of RE2 add longer messages.

Thanks to @peterzhu2118 for both authoring ruby_memcheck and helping
find the source of these leaks.
@mudge mudge closed this as completed Sep 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants