代码之家  ›  专栏  ›  技术社区  ›  Brett Rossier

导致分段错误(sigsegv)或垃圾结果的共享指针(shared-ptr)的Boost Fusion容器

  •  2
  • Brett Rossier  · 技术社区  · 15 年前

    编辑:这个问题似乎只发生在 joint_view shared_ptr . 原始指针在相同的场景中似乎工作得很好,就像在一个简单的fusion容器中同时构建了所有项的共享指针一样,没有向它添加任何内容。详情如下:

    我在用mingw gcc 4.5.1 使用boost fusion容器并将内容取回时遇到特殊问题。我有一个自定义类 std::shared_ptr ,然后交给一个核聚变 make_list() (或 make_vector() 联合视图 . 我使用 fusion::for_each() 并传入一个函数对象以打印出值。如果我迭代的是共享指针的纯fusion容器,而不是 ,或 联合视图 在没有共享指针的情况下,它工作得很好,但在其他情况下,它会出现分段错误或垃圾值。

    下面是一个测试程序,我试图隔离我的问题。有什么想法吗?完全有可能我只是错过了应该/不应该做的事情:(

    #include <iostream>
    #include <memory>
    
    //BOOST SMART POINTERS
    //I only use boost's shared_ptr for ONE test, results are the same.
    #include <boost/shared_ptr.hpp>
    #include <boost/make_shared.hpp>
    
    //BOOST FUSION
    #include <boost/fusion/algorithm/iteration/for_each.hpp>
    #include <boost/fusion/include/for_each.hpp>
    #include <boost/fusion/container/generation/make_list.hpp>
    #include <boost/fusion/include/make_list.hpp>
    #include <boost/fusion/container/generation/make_vector.hpp>
    #include <boost/fusion/include/make_vector.hpp>
    #include <boost/fusion/algorithm/transformation/push_back.hpp>
    #include <boost/fusion/include/push_back.hpp>
    
    using namespace std;
    using namespace boost::fusion;
    
    struct TestStructInt {
        int test_int;
    
        TestStructInt(int init_num) : test_int(init_num) {};
    };
    
    struct TestStructString {
        string test_string;
    
        TestStructString(string init_str) : test_string(init_str) {};
    };
    
    struct do_junk{
        void operator()(string t) const {
            cout << t << endl;
        }
    
        void operator()(string* t) const {
            cout << *t << endl;
        }
    
        void operator()(std::shared_ptr<int> t) const {
            cout << *t << endl;
        }
    
        void operator()(std::shared_ptr<string> t) const {
            cout << *t << endl;
        }
    
        void operator() (boost::shared_ptr<string> t) const {
            cout << *t << endl;
        }
    
        void operator() (TestStructInt t) const {
            cout << t.test_int << endl;
        }
    
        void operator() (std::shared_ptr<TestStructInt> t) const {
            cout << t->test_int << endl;
        }
    
        void operator() (TestStructString t) const {
            cout << t.test_string << endl;
        }
    
        void operator() (std::shared_ptr<TestStructString> t) const {
            cout << t->test_string << endl;
        }
    
        void operator() (std::shared_ptr<TestStructString*> t) const {
            cout << (*t)->test_string << endl;
        }
    };
    
    int main()
    {
        string foo1 = "foo1";
        string foo2 = "foo2";
        string foo3 = "foo3";
        int bar1 = 1;
        int bar2 = 2;
        int bar3 = 3;
        string* foo1_ptr = &foo1;
        string* foo2_ptr = &foo2;
        string* foo3_ptr = &foo3;
        auto foo1_obj = make_shared<TestStructString>(TestStructString("foo1"));
        auto foo2_obj = make_shared<TestStructString>(TestStructString("foo2"));
        auto foo3_obj = make_shared<TestStructString>(TestStructString("foo3"));
    
        //works fine
        auto list_test1 = make_list(foo1, foo2);
    
        //works fine
        auto list_test2 = make_list(foo1_ptr, foo2_ptr);
    
        //seems to work, but is undefined behavior
        auto list_test3
            = make_list(
                std::make_shared<int>(bar1), std::make_shared<int>(bar2)
            )
        ;
    
        //seems to work, but is undefined behavior
        auto list_test4
            = make_list(
                std::make_shared<string>(foo1), std::make_shared<string>(foo2)
            )
        ;
    
        //seems to work, but is undefined behavior
        auto list_test5
            = make_list(
                std::make_shared<TestStructInt>(TestStructInt(1))
                , std::make_shared<TestStructInt>(TestStructInt(2))
            )
        ;
    
        //seems to work, but is undefined behavior
        auto list_test6
            = make_list(
                std::make_shared<TestStructString>(TestStructString("foo1"))
                , std::make_shared<TestStructString>(TestStructString("foo2"))
            )
        ;
    
        //seems to work, but is undefined behavior
        auto list_test7
            = make_list(TestStructString("foo1"), TestStructString("foo2"))
        ;
    
        //seems to work, but is undefined behavior
        auto joint_view_test1 = push_back(make_list(foo1, foo2), foo3);
    
        //seems to work, but is undefined behavior
        auto joint_view_test2 = push_back(make_list(foo1_ptr, foo2_ptr), foo3_ptr);
    
        //seems to work, but is undefined behavior
        auto joint_view_test3
            = push_back(
                make_list(
                    TestStructString(foo1), TestStructString(foo2)
                )
                , TestStructString(foo3)
            )
        ;
    
        //integer values I pass in are coming out different
        auto joint_view_test4
            = push_back(
                make_list(
                    std::make_shared<int>(bar1), std::make_shared<int>(bar2)
                )
                , make_shared<int>(bar3)
            )
        ;
    
        //pass in foo1, foo2, and foo3, but only get foo3's value back out for each
        auto joint_view_test5
            = push_back(
                make_list(
                    std::make_shared<string>(foo1), std::make_shared<string>(foo2)
                )
                , make_shared<string>(foo3)
            )
        ;
    
        //causes seg fault when running do_junk()
        auto joint_view_test6
            = push_back(
                make_vector(
                    std::make_shared<string>(foo1), std::make_shared<string>(foo2)
                )
                , std::make_shared<string>(foo3)
            )
        ;
    
        //causes seg fault when running do_junk()
        auto joint_view_test7
            = push_back(
                make_list(
                    boost::make_shared<string>(foo1)
                    , boost::make_shared<string>(foo2)
                )
                , boost::make_shared<string>(foo3)
            )
        ;
    
        //integer values I pass in are coming out different
        auto joint_view_test8
            = push_back(
                make_list(
                    std::make_shared<TestStructInt>(TestStructInt(1))
                    , std::make_shared<TestStructInt>(TestStructInt(2))
                )
                , std::make_shared<TestStructInt>(TestStructInt(3))
            )
        ;
    
        //causes seg fault when running do_junk()
        auto joint_view_test9
            = push_back(
                make_list(
                    std::make_shared<TestStructString>(TestStructString("foo1"))
                    , std::make_shared<TestStructString>(TestStructString("foo2"))
                )
                , std::make_shared<TestStructString>(TestStructString("foo3"))
            )
        ;
    
        //causes seg fault when running do_junk()
        auto joint_view_test10
            = push_back(
                make_list(
                    std::make_shared<TestStructString*>(new TestStructString("foo1"))
                    , std::make_shared<TestStructString*>(new TestStructString("foo2"))
                )
                , std::make_shared<TestStructString*>(new TestStructString("foo3"))
            )
        ;
    
        //seems to work, but is undefined behavior
        auto joint_view_test11
            = push_back(
                make_list(
                    foo1_obj
                    , foo2_obj
                )
                , foo3_obj
            )
        ;
    
        cout << "@@ list1" << endl;
        boost::fusion::for_each(list_test1, do_junk());
        cout << "@@ list2" << endl;
        boost::fusion::for_each(list_test2, do_junk());
        cout << "@@ list3" << endl;
        boost::fusion::for_each(list_test3, do_junk());
        cout << "@@ list4" << endl;
        boost::fusion::for_each(list_test4, do_junk());
        cout << "@@ list5" << endl;
        boost::fusion::for_each(list_test5, do_junk());
        cout << "@@ list6" << endl;
        boost::fusion::for_each(list_test6, do_junk());
        cout << "@@ list7" << endl;
        boost::fusion::for_each(list_test7, do_junk());
        cout << "@@ joint_view1" << endl;
        boost::fusion::for_each(joint_view_test1, do_junk());
        cout << "@@ joint_view2" << endl;
        boost::fusion::for_each(joint_view_test2, do_junk());
        cout << "@@ joint_view3" << endl;
        boost::fusion::for_each(joint_view_test3, do_junk());
        cout << "@@ joint_view4" << endl;
        boost::fusion::for_each(joint_view_test4, do_junk());
        cout << "@@ joint_view5" << endl;
        //boost::fusion::for_each(joint_view_test5, do_junk());
        cout << "@@ joint_view6" << endl;
        //boost::fusion::for_each(joint_view_test6, do_junk());
        cout << "@@ joint_view7" << endl;
        //boost::fusion::for_each(joint_view_test7, do_junk());
        cout << "@@ joint_view8" << endl;
        //boost::fusion::for_each(joint_view_test8, do_junk());
        cout << "@@ joint_view9" << endl;
        //boost::fusion::for_each(joint_view_test9, do_junk());
        cout << "@@ joint_view10" << endl;
        //boost::fusion::for_each(joint_view_test10, do_junk());
        cout << "@@ joint_view11" << endl;
        boost::fusion::for_each(joint_view_test11, do_junk());
        cout << "@@" << endl;
    
        return 0;
    }
    
    2 回复  |  直到 14 年前
        1
  •  4
  •   hkaiser    15 年前

    fusion::joint_view 保留它的元素作为引用。您需要非常小心,它不会引用临时项(它们在您的设置中的迭代时间会超出范围)。在你的例子中似乎就是这样。

        2
  •  0
  •   Ana Betts    15 年前

    从示例中我不能百分之百地确定这是您所做的,但是您通常不能在遍历列表时更改列表的内容,否则您的迭代器无效。将您的项目列表排队 加上,然后在最后一次全部加上。