On 18.09.2016 22:40, Eugene V. Lyubimkin wrote: > Thank you. Turned out it is reproducible in release build (at the least on > armel porterbox), but not in debug build. > > I'll look into it.
Ok, something fishy is going on with lambda captures. I believe I found an issue in either std::function or GCC optimizer. Looks like a captured value ("this" in this case) is uninitialized or corrupted, but only if previous lambda captures a certain amount of variables, no matter was it called or not. Ugh. I managed to reduce the code to the following small example: (sid_armhf-dchroot)jackyf@harris:~/smalltests/small-std-function-arm$ cat hm.cpp #include <iostream> #include <functional> struct C { void doCb() { size_t dummy_a = 1; std::cout << "Outside: " << this << std::endl; std::function<void ()> f; f = [this, &dummy_a]() {}; f = [this]() { std::cout << "Inside: " << this << std::endl; }; f(); } }; int main() { C c; c.doCb(); } (sid_armhf-dchroot)jackyf@harris:~/smalltests/small-std-function-arm$ cat Makefile all: g++ -O2 -Wall -Wextra hm.cpp -o hm.e (sid_armhf-dchroot)jackyf@harris:~/smalltests/small-std-function-arm$ ./hm.e Outside: 0xbeaeb5f4 Inside: 0x2 (sid_armhf-dchroot)jackyf@harris:~/smalltests/small-std-function-arm$ ~/valgrind/valgrind-3.12.0~svn20160714 /vg-in-place ./hm.e ==9628== Memcheck, a memory error detector ==9628== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==9628== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info ==9628== Command: ./hm.e ==9628== Outside: 0xbdb6a454 ==9628== Use of uninitialised value of size 4 ==9628== at 0x4916BF6: ??? (in /usr/lib/arm-linux-gnueabihf/libstdc++.so.6.0.22) ==9628== ==9628== Conditional jump or move depends on uninitialised value(s) ==9628== at 0x4916BFC: ??? (in /usr/lib/arm-linux-gnueabihf/libstdc++.so.6.0.22) ==9628== ==9628== Conditional jump or move depends on uninitialised value(s) ==9628== at 0x49179FA: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<unsigned long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, unsigned long) const (in /usr/lib/arm-linux-gnueabihf/libstdc++.so.6.0.22) ==9628== by 0x4917AC5: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, >std::ios_base&, char, void const*) const (in /usr/lib/arm-linux-gnueabihf/libstdc++.so.6.0.22) ==9628== by 0x491FDA3: std::ostream& std::ostream::_M_insert<void const*>(void const*) (in /usr/lib/arm-linux-gnueabihf/libstdc++.so.6.0.22) ==9628== Inside: 0x2 ==9628== ==9628== HEAP SUMMARY: ==9628== in use at exit: 0 bytes in 0 blocks ==9628== total heap usage: 2 allocs, 2 frees, 21,248 bytes allocated ==9628== ==9628== All heap blocks were freed -- no leaks are possible ==9628== ==9628== For counts of detected and suppressed errors, rerun with: -v ==9628== Use --track-origins=yes to see where uninitialised values come from ==9628== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)