[devel] проблема с boost::spirit на i586 и armh

Alexey Sheplyakov asheplyakov на basealt.ru
Пт Дек 18 16:26:47 MSK 2020


On 12/16/20 5:28 PM, Ivan A. Melnikov wrote:
> On Sun, Dec 13, 2020 at 03:35:57AM +0300, Vladislav Zavjalov wrote:
>> Обнаружил странную регрессию в одной из своих программ:
>> на 32-битных архитектурах начались падения (Segmentation fault)
>> где-то в районе boost::spirit (очень смешная библиотека для
>> синтаксического разбора, когда-то давно она меня радовала).
>> Судя по всему, произошло это одновременно с переходом на gcc-10,
>> до этого пакет нормально пересобирался.
>>
>> Сделал тестовый пакет с каким-то минимальным кодом, пытался отлаживать
>> на сборочнице, но точное место поймать пока не смог. Как только правила
>> spirit становятся достаточно длинными - начинает падать.
>> Зато выяснил, что падения лечатся убиранием флага -O2.
>> Может быть, кому-нибудь такой рецепт поможет.
>>
>> Если кто-то захочет покопаться, то код есть тут:
>> http://git.altlinux.org/tasks/263387/gears/2200/git
>> А типичный лог на сборочнице выглядит так:
>> http://git.altlinux.org/tasks/263387/build/2200/i586/log
>> Собираю и запускаю программу дважды: без флага -O2 и с ним.
>> Первый раз все работает, второй - падает.
>> На armh - то же самое.
> 
> 
> Я просто оставлю здесь то, что успел (пока) увидеть:
> 
> [builder на localhost fig]$ g++ -O2 main.cpp fig_mask.cpp   -o main && ./main
> Segmentation fault (core dumped)
> [builder на localhost fig]$ g++ -O2 -fno-tree-sra  main.cpp fig_mask.cpp   -o main && ./main
> OK
> [builder на localhost fig]$ g++-9 -O2 main.cpp fig_mask.cpp   -o main && ./main
> OK
> 
Подтверждаю падение i386 бинарника, собранного g++-10 (неважно - кросс-компилятором, или "родным").
Достаточно даже не -O2, а просто -O.

Программу удалось несколько ужать до

#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_assign_actor.hpp>
using namespace boost::spirit::classic;

int main() {
         const char str[] = " 1 2 3 4 5 6 7 8";
         int f[8] = { 0, -1, -2, -3, -4, -5, -6, -7 };
         rule<> myrule =
                    +blank_p >> (ch_p('*') | int_p[assign_a(f[0])])
                 >> +blank_p >> (ch_p('*') | int_p[assign_a(f[1])])
                 >> +blank_p >> (ch_p('*') | int_p[assign_a(f[2])])
                 >> +blank_p >> (ch_p('*') | int_p[assign_a(f[3])])
                 >> +blank_p >> (ch_p('*') | int_p[assign_a(f[4])])
                 >> +blank_p >> (ch_p('*') | int_p[assign_a(f[5])])
                 >> +blank_p >> (ch_p('*') | int_p[assign_a(f[6])])
                 >> +blank_p >> (ch_p('*') | int_p[assign_a(f[7])])
                 ;
         if (!parse(str, myrule).full){
                 return 1;
         }
         return 0;
}

Если кому интересно - backtrace в приложении.

(gdb) frame 20
(gdb) print p.subj.first_.subj.first_.subj.first_.subj.first_.subj.first_.subj.first_.subj.first_.subj.first_.subj.first_.subj.first_.subj.first_.subj.first_.subj.first_.subj.first_.subj.seco
nd_.subj.second_.actor
{<boost::spirit::classic::assign_action> = {<No data fields>}, ref = @0x0}


----------- следующая часть -----------
#0  ref_value_actor<int, assign_action>::operator()<int> (val_=@0xffffce08: 1, this=0x5655ebc0) at /usr/include/boost/spirit/home/classic/actor/ref_value_actor.hpp:60
#1  attributed_action_policy<int const>::call<ref_value_actor<int, assign_action>, char const*> (val=@0xffffce08: 1, actor=...) at /usr/include/boost/spirit/home/classic/core/scanner/scanner.hpp:131
#2  action_policy::do_action<ref_value_actor<int, assign_action>, int const, char const*> (last=@0xffffcefc: 0xffffcf2d " 2 3 4 5 6 7 8", first=<synthetic pointer>: <optimized out>, val=@0xffffce08: 1, actor=..., this=0xffffcf00) at /usr/include/boost/spirit/home/classic/core/scanner/scanner.hpp:162
#3  action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (this=0x5655ebbc, scan=...) at /usr/include/boost/spirit/home/classic/core/composite/actions.hpp:117
#4  0x565566c4 in alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0x5655ebb8) at /usr/include/boost/detail/compressed_pair.hpp:385
#5  sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0x5655ebb4) at /usr/include/boost/spirit/home/classic/core/composite/sequence.hpp:61
#6  sequence<sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0x5655ebb4) at /usr/include/boost/spirit/home/classic/core/composite/sequence.hpp:60
#7  sequence<sequence<sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0x5655ebb4) at /usr/include/boost/spirit/home/classic/core/composite/sequence.hpp:60
#8  sequence<sequence<sequence<sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0x5655ebb4) at /usr/include/boost/spirit/home/classic/core/composite/sequence.hpp:60
#9  sequence<sequence<sequence<sequence<sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0x5655ebb4) at /usr/include/boost/spirit/home/classic/core/composite/sequence.hpp:60
#10 sequence<sequence<sequence<sequence<sequence<sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0x5655ebb4) at /usr/include/boost/spirit/home/classic/core/composite/sequence.hpp:60
#11 sequence<sequence<sequence<sequence<sequence<sequence<sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0x5655ebb4) at /usr/include/boost/spirit/home/classic/core/composite/sequence.hpp:60
#12 sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (this=0x5655ebb4, scan=...) at /usr/include/boost/spirit/home/classic/core/composite/sequence.hpp:60
#13 0x565569c0 in sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0x5655ebb4) at /usr/include/boost/detail/compressed_pair.hpp:382
#14 sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0x5655ebb4) at /usr/include/boost/spirit/home/classic/core/composite/sequence.hpp:60
#15 sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0x5655ebb4) at /usr/include/boost/spirit/home/classic/core/composite/sequence.hpp:60
#16 sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (this=0x5655ebb4, scan=...) at /usr/include/boost/spirit/home/classic/core/composite/sequence.hpp:60
#17 0x56556b7f in sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0x5655ebb4) at /usr/include/boost/detail/compressed_pair.hpp:382
#18 sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<positive<blank_parser>, alternative
<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0x5655ebb4) at /usr/include/boost/spirit/home/classic/core/composite/sequence.hpp:60
#19 sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0x5655ebb4) at /usr/include/boost/spirit/home/classic/core/composite/sequence.hpp:60
#20 impl::concrete_parser<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<sequence<positive<blank_parser>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, positive<blank_parser>>, alternative<chlit<char>, action<int_parser<int, 10, 1u, -1>, ref_value_actor<int, assign_action>>>>, scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>, nil_t>::do_parse_virtual (this=0x5655ebb0, scan=...) at /usr/include/boost/spirit/home/classic/core/non_terminal/impl/rule.ipp:241
#21 0x56556367 in impl::rule_base<rule<nil_t, nil_t, nil_t>, rule<nil_t, nil_t, nil_t> const&, nil_t, nil_t, nil_t>::parse_main<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0xffffcef8) at /usr/include/boost/spirit/home/classic/core/impl/match.ipp:66
#22 impl::rule_base<rule<nil_t, nil_t, nil_t>, rule<nil_t, nil_t, nil_t> const&, nil_t, nil_t, nil_t>::parse<scanner<char const*, scanner_policies<iteration_policy, match_policy, action_policy>>> (scan=..., this=0xffffcef8) at /usr/include/boost/spirit/home/classic/core/non_terminal/impl/rule.ipp:174
#23 parse<char const*, rule<nil_t, nil_t, nil_t>> (p=..., last=<synthetic pointer>: <optimized out>, first_=<synthetic pointer>: <optimized out>) at /usr/include/boost/spirit/home/classic/core/impl/parser.ipp:30
#24 parse<char, rule<nil_t, nil_t, nil_t>> (p=..., str=0xffffcf2b " 1 2 3 4 5 6 7 8") at /usr/include/boost/spirit/home/classic/core/impl/parser.ipp:47
#25 main () at main.cpp:18


Подробная информация о списке рассылки Devel