代码之家  ›  专栏  ›  技术社区  ›  Wrotcod

其他线程堆栈上的可用内存无效

  •  -1
  • Wrotcod  · 技术社区  · 7 年前

    typedef std::shared_ptr<Parameters_parser> sh_params_t;
    typedef std::shared_ptr<Shared_objects> sh_obj_t;
    class Abstract_thread {
        public:
            Abstract_thread(sh_params_t params, sh_obj_t sh_obj): 
                params(params), sh_obj(sh_obj) {}
            virtual ~Abstract_thread() = 0;
            virtual void launch() = 0;
         protected:
            /** The shared parameters of the execution. */
            sh_params_t params; 
            /** The Shared_objects containing all queues. */
            sh_obj_t sh_obj;
    };
     inline Abstract_thread::~Abstract_thread(){
        cout << "Abstract_thread destructor with params: "
            << params.use_count() << " and sh_obj: " << 
            sh_obj.use_count() << endl;
    }
    class Interface_sniffer : public Abstract_thread {
        Interface_sniffer(sh_params_t params, sh_obj_t sh_obj): 
            Abstract_thread(params, sh_obj) {}
        ~Interface_sniffer(){
            cout << "Good bye from Interface_sniffer1 !" << endl;
         }
        void launch(){
            try {
                while(true)
                    interruption_point();
             } catch(thread_interrupted const& e) {
                 disable_interruption di;
                 delete this;
             }
        }
    };
    

    然后,大体上:

    void main(int argc, char* argv[]) {
        sh_obj_t sh_obj = std::make_shared<Shared_objects>();
        sh_params_t params = std::make_shared<Parameters_parser>();
        Interface_sniffer sniffer1(params, sh_obj);
        boost::thread t1(bind(&Interface_sniffer::launch, &sniffer1));
        boost::this_thread::sleep_for(boost::chrono::seconds(5));
        cout << "trying to stop 1" << endl;
        t1.interrupt();
        t1.join();
    }
    

    Parameters_parser Shared_objects 是基本类,包含仅由我的线程读取的字段,或者使用boost::lockfree::queue,这应该不是问题所在。

    所以当我运行它时,valgrind告诉我:

    trying to stop 1
    Good bye from Interface_sniffer1 !
    Abstract_thread destructor with params: 2 and sh_obj: 2
    ==2095== Thread 2:
    ==2095== Invalid free() / delete / delete[] / realloc()
    ==2095==    at 0x4C2F24B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==2095==    by 0x41A1C1: Interface_sniffer::~Interface_sniffer() (interface_sniffer.cpp:34)
    ==2095==    by 0x41A6DC: Interface_sniffer::launch() (interface_sniffer.cpp:69)
    ==2095==    by 0x44D1E8: void std::_Mem_fn_base<void (Interface_sniffer::*)(), true>::operator()<, void>(Interface_sniffer*) const (in somewhere)
    ==2095==    by 0x44D162: void std::_Bind<std::_Mem_fn<void (Interface_sniffer::*)()> (Interface_sniffer*)>::__call<void, , 0ul>(std::tuple<>&&, std::_Index_tuple<0ul>) (in somewhere)
    ==2095==    by 0x44D115: void std::_Bind<std::_Mem_fn<void (Interface_sniffer::*)()> (Interface_sniffer*)>::operator()<, void>() (in somewhere)
    ==2095==    by 0x44CB9B: boost::detail::thread_data<std::_Bind<std::_Mem_fn<void (Interface_sniffer::*)()> (Interface_sniffer*)> >::run() (thread.hpp:116)
    ==2095==    by 0x50C95D4: ??? (in /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.58.0)
    ==2095==    by 0x604D6B9: start_thread (pthread_create.c:333)
    ==2095==    by 0x636A3DC: clone (clone.S:109)
    ==2095==  Address 0xfff000240 is on thread 1's stack
    ==2095==  in frame #3, created by main (main.cpp:23)
    ==2095== 
    

    因此,它假装我正在删除位于主线程堆栈上的某些内容(我假设 params sh_obj ),但事实并非如此,因为shared\u ptr指向的对象位于堆上。我能做什么?我应该通过考试吗 shared_ptr<>* 到我的线程,并调用 params->reset() sh_obj->reset() 在析构函数中手动?

    1 回复  |  直到 7 年前
        1
  •  3
  •   John Zwinck    7 年前

    Interface_sniffer 包含以下代码:

    delete this;
    

    main()

    Interface_sniffer sniffer1(params, sh_obj);
    

    因此,您正在删除堆栈分配的对象,正如valgrind所说。这是未定义的行为。

    delete this