yhirose / cpp-peglib

A single file C++ header-only PEG (Parsing Expression Grammars) library
MIT License
884 stars 112 forks source link

Initialize the parser in shared library(linux platform) causing error for parser's operator= #130

Closed lanphon closed 3 years ago

lanphon commented 3 years ago

I've tried to use peglib on my personal project. When splitting the parser initialization to a shared library, it seems Linux platform with gcc would causing error. It's of no problem for macOS and Windows.

0x00007fffff4e2f2d in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&) ()
   from /lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) bt
#0  0x00007fffff4e2f2d in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&) ()
   from /lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00007fffff72482b in peg::parser::operator= (this=0x7fffff7afcc0 <representation_t::g_parser>) at /home/xinzhao/repos/t0/tools/include/peglib.h:3852
#2  0x00007fffff70e0e4 in representation_t::init (this=0x7fffff7af9c2 <_as>) at /home/xinzhao/repos/t0/tools/source/represent.cpp:26
#3  0x00007fffff6e7d16 in representation_t::representation_t (this=0x7fffff7af9c2 <_as>) at /home/xinzhao/repos/t0/tools/include/represent.h:16
#4  0x00007fffff6dba80 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /home/xinzhao/repos/t0/tools/source/testlang.cpp:14
#5  0x00007fffff6dbab7 in _GLOBAL__sub_I_testlang.cpp(void) () at /home/xinzhao/repos/t0/tools/source/testlang.cpp:25
#6  0x00007fffff7c1b8a in ?? () from /lib64/ld-linux-x86-64.so.2
#7  0x00007fffff7c1c91 in ?? () from /lib64/ld-linux-x86-64.so.2
#8  0x00007fffff7b113a in ?? () from /lib64/ld-linux-x86-64.so.2
#9  0x0000000000000001 in ?? ()
#10 0x00007ffffffee9a7 in ?? ()
#11 0x0000000000000000 in ?? ()
(gdb)

A simple sample to reproduce this case is placed into here. I've checked with following environments, all of which could reproduce it:

yhirose commented 3 years ago

@lanphon, thanks for the report. How can I build and run your demo?

lanphon commented 3 years ago

Just clone the project from https://github.com/lanphon/peglib_debug, and do following operations:

$ cd peglib_debug
$ cmake -S . -B build
$ cmake --build build
$ bin64/test_init

And on Linux platform, the bug will be reproduced. I've used the peglib in a shared object, and use teh code from another executable test_init. The callstack of gdb showes it failures to do the parser's assign-copy.

yhirose commented 3 years ago

@lanphon, this should work. Hope it helps.

image

lanphon commented 3 years ago

@yhirose it seems the bug is still not solved yet. with the latest code, it still crash. On the other hand, I could avoid this error by specifying the move-assigment manually by:

  parser& operator=(parser&& rhs)
    {
    if (&rhs != this)
      {
      log = std::move(rhs.log);
      grammar_ = std::move(rhs.grammar_);
      start_ = rhs.start_; // cannot be start_ = std::move(rhs.start_), which would cause the error
      }
    return *this;
    }

it seems when moving the start_, the auto-synthesis move-assignment operator= would failure(it's strange since it's just a literal string). After specifying the move assignment operator=, the error disappears, but a memory leak is reported, said there are 5 char(just the length of the "ROOT" string) leaking. I've tried to rename the "ROOT" of the PEG to other one, and shows the leaked size match with the PEG root node name size.

==243707== Memcheck, a memory error detector
==243707== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==243707== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==243707== Command: ./test_init
==243707==
==243707==
==243707== HEAP SUMMARY:
==243707==     in use at exit: 4,573 bytes in 35 blocks
==243707==   total heap usage: 1,622 allocs, 1,587 frees, 186,121 bytes allocated
==243707==
==243707== 5 bytes in 1 blocks are definitely lost in loss record 1 of 16
==243707==    at 0x483ADEF: operator new(unsigned long) (vg_replace_malloc.c:342)
==243707==    by 0x4BBA0BF: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (basic_string.tcc:265)
==243707==    by 0x4BBA43E: assign (basic_string.h:1366)
==243707==    by 0x4BBA43E: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (basic_string.h:667)
==243707==    by 0x49C829C: peg::parser::operator=(peg::parser&&) (peglib.h:3648)
==243707==    by 0x49B2F43: representation_t::init() (represent.cpp:27)
==243707==    by 0x498F725: representation_t::representation_t() (represent.h:16)
==243707==    by 0x4983ECB: __static_initialization_and_destruction_0(int, int) (testlang.cpp:14)
==243707==    by 0x4983EFE: _GLOBAL__sub_I_testlang.cpp (testlang.cpp:25)
==243707==    by 0x40112DD: call_init.part.0 (in /usr/lib/ld-2.32.so)
==243707==    by 0x40113C7: _dl_init (in /usr/lib/ld-2.32.so)
==243707==    by 0x40020C9: ??? (in /usr/lib/ld-2.32.so)
==243707==
==243707== 4,568 (72 direct, 4,496 indirect) bytes in 1 blocks are definitely lost in loss record 16 of 16
==243707==    at 0x483ADEF: operator new(unsigned long) (vg_replace_malloc.c:342)
==243707==    by 0x49F5349: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > >, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) (new_allocator.h:115)
==243707==    by 0x49F23CC: std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > >, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator<std::_Sp_counted_ptr_inplace<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > >, (__gnu_cxx::_Lock_policy)2> >&, unsigned long) (alloc_traits.h:460)
==243707==    by 0x49EC727: std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > >, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > >, (__gnu_cxx::_Lock_policy)2> > >(std::allocator<std::_Sp_counted_ptr_inplace<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > >, (__gnu_cxx::_Lock_policy)2> >&) (allocated_ptr.h:97)
==243707==    by 0x49E4FF7: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > >>(std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > >*&, std::_Sp_alloc_shared_tag<std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > > >) (shared_ptr_base.h:680)
==243707==    by 0x49DD1CD: std::__shared_ptr<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > >, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > >>(std::_Sp_alloc_shared_tag<std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > > >) (shared_ptr_base.h:1371)
==243707==    by 0x49D6050: std::shared_ptr<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > >::shared_ptr<std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > >>(std::_Sp_alloc_shared_tag<std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > > >) (shared_ptr.h:408)
==243707==    by 0x49D0A5B: std::shared_ptr<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > > std::allocate_shared<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > >>(std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > > const&) (shared_ptr.h:860)
==243707==    by 0x49CA109: std::shared_ptr<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > > > std::make_shared<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, peg::Definition, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, peg::Definition> > >>() (shared_ptr.h:876)
==243707==    by 0x49B700C: peg::ParserGenerator::Data::Data() (peglib.h:2679)
==243707==    by 0x49C6B38: peg::ParserGenerator::perform_core(char const*, unsigned long, std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<peg::Ope>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<peg::Ope> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::function<void (unsigned long, unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>) (peglib.h:3156)
==243707==    by 0x49B6B85: peg::ParserGenerator::parse(char const*, unsigned long, std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<peg::Ope>, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<peg::Ope> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::function<void (unsigned long, unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>) (peglib.h:2644)
==243707==
==243707== LEAK SUMMARY:
==243707==    definitely lost: 77 bytes in 2 blocks
==243707==    indirectly lost: 4,496 bytes in 33 blocks
==243707==      possibly lost: 0 bytes in 0 blocks
==243707==    still reachable: 0 bytes in 0 blocks
==243707==         suppressed: 0 bytes in 0 blocks
==243707==
==243707== For lists of detected and suppressed errors, rerun with: -s
==243707== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)