2016-12-01 21 views
2

私はポーリングデータから外部ハードウェアを作成し、そのデータを信号で送信します。ブーストセマフォー原因segfault

私のコードは、共有メモリのsmaphoreで呼び出されるのを待っているときにsegfaultを引き起こし、なぜその理由が分かりません。

以下、私がやっていることの小さな例です。 基本的に2つのブースト・スレッドを開始します.1つは共有メモリーにデータを書き込み、もう1つはデータを読み込みます。

メインは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; 
}; 

源:私はすでに同じ結果とブーストとstdミューテックスを試みた

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; 
     } 
    } 
} 

。 共有/マップされたメモリを間違って処理しますか?ここで

+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; 
} 

、あなたはすぐにtryブロック出るようスコープの外に出る共有オブジェクトへのポインタ(m_sharedMemory)を格納します。ブーム!プロデューサーで

同じ問題:決定論的なストレージ寿命を持つ++

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

ありがとう!私はスコープ内のマップされたメモリを保持しているスレッドの(今)奇妙なアイデアを持っていた - しかし、スレッドはブーストスレッドをbeeしていない。だから私はそれを台無しにした。 – user7236868

+0

@ user7236868全く問題はありません。あなたの例ではstd :: threadを使って中断ポイントを落としてください:http://coliru.stacked-crooked.com/a/0863e2e3aed1773e – sehe

関連する問題