2016-12-01 124 views
2

我想轮询数据形式外部硬件并通过信号发送数据。boost信号量导致段错误

我的代码导致段错误,当在共享内存中的smaphore等待被调用,我不明白为什么。

下面是我正在做的一个小例子。 基本上启动两个boost线程,一个在共享内存中写入数据,另一个在共享内存中读取数据。

主要只是启动ThreadHandler,并停止ThreadHandler。

头:

struct SharedData{ 
    boost::interprocess::interprocess_semaphore sem; 
    int data; 
    bool newData; 
    SharedData():sem(1),newData(false){} 
}; 

class ThreadHandler 
{ 
public: 
    ThreadHandler(); 
    void start(); 
    void stop(); 
    boost::thread *m_Thread; 
    boost::thread *m_doerThread; 
    void doStuff(); 
    void createSharedMemory(); 
    void removeSharedMemory(); 
    SharedData* m_sharedMemory; 
}; 

来源:

void getStuff(int id); 


void ThreadHandler::start(){ 
    createSharedMemory(); 
    m_doerThread = new boost::thread(boost::bind(&ThreadHandler::doStuff,boost::ref(*this))); 
    m_Thread = new boost::thread(boost::bind(&getStuff,1)); 
} 

void ThreadHandler::stop(){ 
    m_Thread->interrupt(); 
    m_doerThread->interrupt(); 

    m_Thread->join(); 
    m_doerThread->join(); 
} 

void ThreadHandler::createSharedMemory(){ 
    removeSharedMemory(); 
    try{ 
     boost::interprocess::shared_memory_object sharedObj(boost::interprocess::create_only,SHARED_MEMORY ,boost::interprocess::read_write); 
     sharedObj.truncate(sizeof(SharedData)); 
     boost::interprocess::mapped_region mappedObj(sharedObj,boost::interprocess::read_write); 
     SharedData* helper = (SharedData*)mappedObj.get_address(); 
     m_sharedMemory = new (helper) SharedData; 
    }catch(boost::interprocess::interprocess_exception &ex){ 
     std::cout<<ex.what()<<std::endl; 
    }catch(std::exception &ex){ 
     std::cout<<ex.what()<<std::endl; 
    } 
} 

void ThreadHandler::removeSharedMemory(){ 
    boost::interprocess::shared_memory_object::remove(SHARED_MEMORY); 
} 

void ThreadHandler::doStuff(){ 
    while(1){ 
     try{ 
      boost::this_thread::yield(); 
      m_sharedMemory->sem.wait(); 
      while(!m_sharedMemory->newData){ 
       m_sharedMemory->sem.post(); 
       boost::this_thread::interruption_point(); 
       boost::this_thread::yield(); 
       m_sharedMemory->sem.wait(); 
      } 
      //doStuff 
      m_sharedMemory->newData=false; 
      m_sharedMemory->sem.post(); 
     }catch(boost::thread_interrupted &interupt){ 
      break; 
     }catch(std::exception &ex){ 
      std::cout<<ex.what()<<std::endl; 
     }catch(...){ 
      std::cout<<"exception"<<std::endl; 
     } 
    } 
} 

void getStuff(int id){ 
    SharedData* m_sharedMemory; 
    try{ 
     boost::interprocess::shared_memory_object sharedObj(boost::interprocess::open_only,SHARED_MEMORY,boost::interprocess::read_write); 
     boost::interprocess::mapped_region mappedObj(sharedObj,boost::interprocess::read_write); 
     m_sharedMemory = static_cast<SharedData*>(mappedObj.get_address()); 
    }catch(std::exception &ex){ 
     std::cout<<ex.what()<<std::endl; 
    } 
    while(1){ 
     try{ 
      //get Data from hardware 
      int i =1; 
      m_sharedMemory->sem.wait(); 
      while(m_sharedMemory->newData){ 
       m_sharedMemory->sem.post(); 
       boost::this_thread::interruption_point(); 
       boost::this_thread::yield(); 
       m_sharedMemory->sem.wait(); 
      } 
      memcpy(&(m_sharedMemory->data),&i,sizeof(int)); 
      m_sharedMemory->newData=true; 
      m_sharedMemory->sem.post(); 

     }catch(boost::thread_interrupted&){ 
      break; 
     }catch(std::exception &ex){ 
      std::cout<<ex.what()<<std::endl; 
     } 
    } 
} 

我已经尝试提升和std互斥具有相同的结果。 我处理共享/映射的内存有问题吗?

+0

什么是与所有的指针,而不是释放对象时动态分配?你来自Java还是C#背景? –

+0

对不起,我必须在发帖前删除它们 – user7236868

回答

0
try { 
    bip::shared_memory_object sharedObj(bip::create_only, SHARED_MEMORY, bip::read_write); 
    sharedObj.truncate(sizeof(SharedData)); 
    bip::mapped_region mappedObj(sharedObj, bip::read_write); 
    SharedData *helper = (SharedData *)mappedObj.get_address(); 
    m_sharedMemory = new (helper) SharedData; 
} catch (bip::interprocess_exception &ex) { 
    std::cout << ex.what() << std::endl; 
} catch (std::exception &ex) { 
    std::cout << ex.what() << std::endl; 
} 

在这里,你存储指针(m_sharedMemory)到共享对象,只要try块退出超出范围。繁荣!在制片人

同样的问题:++具有确定性的存储寿命

SharedData *m_sharedMemory; 
try { 
    bip::shared_memory_object sharedObj(bip::open_only, SHARED_MEMORY, bip::read_write); 
    bip::mapped_region mappedObj(sharedObj, bip::read_write); 
    m_sharedMemory = static_cast<SharedData *>(mappedObj.get_address()); 
} catch (std::exception &ex) { 
    std::cout << ex.what() << std::endl; 
} 

C,并没有垃圾收集。正如评论者所暗示的那样,只需洒上new左右你没有任何好处。事实上,这会让你的生活变得更糟,因为现在你必须担心清理和异常安全。

取而代之,使用自动存储持续时间(堆栈,本地人,成员),但确保您的对象的生命周期足够使用它的所有代码。

这里,似乎你想要做什么固定的演示:

Live On Coliru

#include <boost/interprocess/mapped_region.hpp> 
#include <boost/interprocess/shared_memory_object.hpp> 
#include <boost/interprocess/sync/interprocess_semaphore.hpp> 
#include <boost/thread.hpp> 
#include <fstream> 

#define SHARED_MEMORY "29939FC9-D56B-43A0-AED3-239B8DD4182B" 

namespace bip = boost::interprocess; 

struct SharedData { 
    bip::interprocess_semaphore sem; 
    int data; 
    bool newData; 
    SharedData() : sem(1), newData(false) {} 
}; 

struct ThreadHandler { 
    ThreadHandler() { } 
    void start(); 
    void stop(); 
    boost::thread m_producer; 
    boost::thread m_consumer; 
    void consumer_func(); 

    void createSharedMemory(); 
    void removeSharedMemory(); 

    bip::shared_memory_object m_sharedObj; 
    bip::mapped_region m_mappedObj; 
    SharedData *m_sharedMemory = nullptr; 

    ~ThreadHandler() { 
     stop(); 
    } 
}; 

void producer_func(int); 

void ThreadHandler::start() { 
    createSharedMemory(); 
    m_consumer = boost::thread(&ThreadHandler::consumer_func, this); 
    m_producer = boost::thread(&producer_func, 1); 
} 

void ThreadHandler::stop() { 
    m_producer.interrupt(); 
    m_consumer.interrupt(); 

    m_producer.join(); 
    m_consumer.join(); 
} 

void ThreadHandler::createSharedMemory() { 
    removeSharedMemory(); 
    try { 
     m_sharedObj = bip::shared_memory_object(bip::create_only, SHARED_MEMORY, bip::read_write); 
     m_sharedObj.truncate(sizeof(SharedData)); 
     m_mappedObj = bip::mapped_region(m_sharedObj, bip::read_write); 
     m_sharedMemory = new (m_mappedObj.get_address()) SharedData; 
    } catch (bip::interprocess_exception &ex) { 
     std::cout << ex.what() << std::endl; 
    } catch (std::exception &ex) { 
     std::cout << ex.what() << std::endl; 
    } 
} 

void ThreadHandler::removeSharedMemory() { 
    try { 
     m_sharedMemory = nullptr; 
     bip::shared_memory_object::remove(SHARED_MEMORY); 
    } catch(...) {} 
} 

void ThreadHandler::consumer_func() { 
    while (1) { 
     try { 
      boost::this_thread::yield(); 
      m_sharedMemory->sem.wait(); 
      while (!m_sharedMemory->newData) { 
       m_sharedMemory->sem.post(); 
       boost::this_thread::interruption_point(); 
       boost::this_thread::yield(); 
       m_sharedMemory->sem.wait(); 
      } 
      // doStuff 
      std::cout << "." << std::flush; 
      m_sharedMemory->newData = false; 
      m_sharedMemory->sem.post(); 
     } catch (boost::thread_interrupted &interupt) { 
      break; 
     } catch (std::exception &ex) { 
      std::cout << ex.what() << std::endl; 
     } catch (...) { 
      std::cout << "exception" << std::endl; 
     } 
    } 
} 

void producer_func(int) { 
    try { 
     bip::shared_memory_object sharedObj(bip::open_only, SHARED_MEMORY, bip::read_write); 
     bip::mapped_region mappedObj(sharedObj, bip::read_write); 
     auto m_sharedMemory = static_cast<SharedData *>(mappedObj.get_address()); 

     while (1) { 
      try { 
       boost::this_thread::sleep_for(boost::chrono::milliseconds(50)); 
       // get Data from hardware 
       int i = 1; 
       m_sharedMemory->sem.wait(); 
       while (m_sharedMemory->newData) { 
        m_sharedMemory->sem.post(); 
        boost::this_thread::interruption_point(); 
        boost::this_thread::yield(); 
        m_sharedMemory->sem.wait(); 
       } 
       memcpy(&(m_sharedMemory->data), &i, sizeof(int)); 
       m_sharedMemory->newData = true; 
       m_sharedMemory->sem.post(); 

      } catch (boost::thread_interrupted &) { 
       break; 
      } catch (std::exception &ex) { 
       std::cout << ex.what() << std::endl; 
      } 
     } 
    } catch (std::exception &ex) { 
     std::cout << ex.what() << std::endl; 
    } 
} 

int main() { 
    ThreadHandler th; 
    th.start(); 
    boost::this_thread::sleep_for(boost::chrono::seconds(3)); 
} 
+0

添加了一个清理好的示例http://coliru.stacked-crooked.com/a/813cb99c6b5ffaad(Coliru不支持共享内存,Wandbox ](http://melpon.org/wandbox/permlink/2Sv7GCrs64yIioE2)) – sehe

+0

非常感谢!我对线程保持映射内存的(现在)奇怪的想法 - 但该线程不是一个助推线程。所以我搞砸了。 – user7236868

+0

@ user7236868完全没问题;只需删除中断点:http://coliru.stacked-crooked.com/a/0863e2e3aed1773e – sehe