I have some weird behaviours when using boost::adaptors::filter. Let's note that I created a small example that respects my larger project contraints. With the following short example I have a segfault if compiled with GCC optimisations, and works like a charm with no optimisation. Of course, my goal is to have it working with -O3.
#include <cstdlib>#include <cstdio>#include <memory>#include <boost/range/adaptors.hpp>#include <boost/range/any_range.hpp>#include <vector>#include <iostream>class TestClass { std::string _id="";public: explicit TestClass(std::string i) : _id(i) {} std::string id() {return _id;}};typedef std::unique_ptr<TestClass> TestClassPtr;typedef boost::any_range<TestClass*, boost::forward_traversal_tag> IterTestClass;typedef std::vector<TestClassPtr> VecTestClass;IterTestClass get_iter(const VecTestClass &in) { return boost::adaptors::transform( boost::adaptors::filter(in, [](const TestClassPtr &e) { return e->id() == "a"; } ), [](const TestClassPtr &e) ->TestClass* {return e.get();} );}int main(int argc, char **argv) { VecTestClass val; for(size_t i=0 ; i < argc ; ++i) val.push_back(TestClassPtr(new TestClass(argv[i]))); for(TestClass *v : get_iter(val)) std::cout << v->id() << std::endl; return EXIT_SUCCESS;}
Good run (opti -O0):
g++ -o boostbug main.cpp -O0 -g -std=gnu++17./boostbug b ab a a b caa
Segfault run (opti -01 or -03):
g++ -o boostbug main.cpp -O1 -g -std=gnu++17./boostbug b ab a a b c#0 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (__str=<error reading variable: Cannot access memory at address 0xf>, this=0x7fffffffd910) at /usr/include/c++/11.2.0/bits/basic_string.h:459#1 TestClass::id[abi:cxx11]() (this=0x7) at src/boostbug/main.cpp:14#2 main (argc=0x7, argv=<optimized out>) at src/boostbug/main.cpp:35#3 0x00007ffff7a8a310 in __libc_start_call_main () from /usr/lib/libc.so.6#4 0x00007ffff7a8a3c1 in __libc_start_main_impl () from /usr/lib/libc.so.6#5 0x00005555555561a5 in _start ()
Extremely weird run (opti -O2):
g++ -o boostbug main.cpp -O2 -g -std=gnu++17./boostbug b ab a a b ccc
Any idea?
Config:
- ArchLinux
- gcc (GCC) 11.2.0
- boost 1.78.0-2
Solution is to change the declaration of the type IterTestClass to add a 3rd argument to the any_range declaration, such as:
typedef boost::any_range<TestClass*, boost::forward_traversal_tag, TestClass*> IterTestClass;