2017-08-14 42 views
-1

我想中断正常使用共享内存的线程,但事实并非如此简单。我正在使用Boost.lockfree和Boost.Thread。下面是我创建的类:无法在其他线程的堆栈上释放内存

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_parserShared_objects是基本类,包含字段只能由我的线程,或升压::阅读lockfree ::队列,这不应该是问题。

所以,当我运行它,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== 

所以假装我正在删除一些位于主线程的堆栈(我假设paramssh_obj),但事实并非如此,因为由shared_ptr指向的对象位于堆上。我能做什么 ?我是否应该将shared_ptr<>*传递给我的线程,并在析构函数中手动调用params->reset()sh_obj->reset()

回答

3

Interface_sniffer包含此代码:

delete this; 

而且main()包含此代码:

Interface_sniffer sniffer1(params, sh_obj); 

所以你删除一个堆栈分配的对象,正是因为Valgrind的说。这是未定义的行为。

由于delete this是非常不寻常的(虽然有时甚至有用),但重新考虑为什么以及如果您需要它是个好主意。从你的代码中不明显你确实需要它。