提升信号量导致段错误

时间:2016-12-01 15:29:46

标签: c++ boost segmentation-fault ipc

我希望轮询数据来自外部硬件并通过信号发送数据。

我的代码会导致段错误,当等待共享内存中的smaphore时,我无法找出原因。

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

main只是启动ThreadHandler, sleeps 并停止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;
        }
    }
}

我已经尝试过具有相同结果的boost和std互斥锁。 我是否错误地处理共享/映射内存?

1 个答案:

答案 0 :(得分: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));
}