共享内存环缓冲区崩溃

时间:2015-07-03 14:09:52

标签: c++ qt memory shared

我用QT编写了一个共享内存环缓冲区,结果发现它在一个进程中运行良好,只有一个用户和一个编写器。如果我尝试从第二个进程读取数据,那么连接的第一个进程会发生seg故障。也许我忽略了什么?

标题文件

#ifndef SHAREDMEMORYRINGBUFFER_H
#define SHAREDMEMORYRINGBUFFER_H

#include <QObject>
#include <QSharedMemory>

class SharedMemoryRingBuffer : public QObject
{
    Q_OBJECT
public:
    struct SharedMemoryAttributes {
        int32_t readPosition;
        int32_t writePosition;
        int32_t size;
        int32_t* data;
    };
    explicit SharedMemoryRingBuffer(QString sharedMemoryName, int32_t size, QObject *parent = 0);
    ~SharedMemoryRingBuffer();
    int write(int32_t frame);
    int32_t read();

    int32_t length();
    int32_t readPosition();
    int32_t writePosition();

    int avaibleSize();
    int isEmpty();
    void empty();
    int isFull();



private:
    SharedMemoryAttributes *_attributes;
    int32_t _writePosition;
    int32_t _readPosition;
    int32_t _length;
    QSharedMemory *_sharedMemory;
    int _headSize;
signals:
    void readFrame(QString name);
public slots:
};

#endif // SHAREDMEMORYRINGBUFFER_H

和CPP文件:

#include "sharedmemoryringbuffer.h"
#include <QDebug>
#define DEBUGGINGNAME "[SharedMemoryRingbuffer]"

SharedMemoryRingBuffer::SharedMemoryRingBuffer(QString sharedMemoryName, int32_t size, QObject *parent) : QObject(parent)
{
    int sizeOfData = sizeof(int32_t) * (size);
    int sizeOfHeader = sizeof(SharedMemoryAttributes);
    _sharedMemory = new QSharedMemory(sharedMemoryName);

    if (!_sharedMemory->attach()) {
        if (!_sharedMemory->create(sizeOfData+sizeOfHeader, QSharedMemory::ReadWrite )) {
            qDebug() << DEBUGGINGNAME << "Could not create shared memory object, aborting ...";
            qDebug() << DEBUGGINGNAME << _sharedMemory->errorString();
            //TODO: exit call
            return;
        }
    }

    _sharedMemory->lock();
    _attributes = reinterpret_cast<SharedMemoryAttributes*>(_sharedMemory->data());
    _attributes->readPosition = 0;
    _attributes->writePosition = 0;
    _attributes->size = size + 1;
    _attributes->data = (int32_t*) _sharedMemory->data() + sizeOfHeader;
    _sharedMemory->unlock();
}

SharedMemoryRingBuffer::~SharedMemoryRingBuffer()
{
    _sharedMemory->detach();
    delete _sharedMemory;
}

int SharedMemoryRingBuffer::write(int32_t frame)
{
    _sharedMemory->lock();
    if ( !isFull() ) {
        _attributes->data[writePosition()] = frame;
        if (writePosition() + 1 >= _attributes->size) _attributes->writePosition = 0;
        else _attributes->writePosition += 1;
        _sharedMemory->unlock();
        return 1;
    }
    _sharedMemory->unlock();
    return 0;
}


/**
 * @brief SharedMemoryRingBuffer::read
 * @return
 * if the buffer is empty this functions returns the last readable value
 *
 */
int32_t SharedMemoryRingBuffer::read()
{
    _sharedMemory->lock();
    int32_t frame = _attributes->data[readPosition()];
    if ( readPosition() != writePosition() ) {
        if (readPosition() + 1 >= _attributes->size ) _attributes->readPosition = 0;
        else _attributes->readPosition += 1;
        emit readFrame(_sharedMemory->key());
    }
    _sharedMemory->unlock();
    return frame;
}

int32_t SharedMemoryRingBuffer::length()
{
    if(readPosition() <= writePosition()) {
        return writePosition() - readPosition();
    } else {
        return readPosition() - writePosition();
    }
}

int32_t SharedMemoryRingBuffer::readPosition()
{
    return _attributes->readPosition;
}

int32_t SharedMemoryRingBuffer::writePosition()
{
    return _attributes->writePosition;
}

int SharedMemoryRingBuffer::avaibleSize()
{
    return -1;
}

int SharedMemoryRingBuffer::isEmpty()
{
    if ( readPosition() == writePosition() ) return 1;
    else return 0;
}

void SharedMemoryRingBuffer::empty()
{

}

int SharedMemoryRingBuffer::isFull()
{
    if ((writePosition() + 1) % _attributes->size == readPosition()) return 1;
    else return 0;
}

2 个答案:

答案 0 :(得分:0)

这个初始化:

07-05 12:40:08.348  23286-23286/? E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: com.example.micor.projectsero2, PID: 23286
android.util.SuperNotCalledException: Activity     {com.example.micor.projectsero2/com.example.micor.projectsero2.MainActivity} did not call through to super.onCreate()
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2335)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2441)
        at android.app.ActivityThread.access$800(ActivityThread.java:162)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1349)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5431)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:913)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:706)

看起来不正确,因为传递给_sharedMemory-&gt; create()的大小只分配足够的&#34;数据&#34;大小元素的空间,而不是大小+ 1.为什么+1在那里?

答案 1 :(得分:0)

所以我找到了一个非常明显的解决方案。如果第二个进程连接到共享内存,则不应将头尾位置设置为0。

这是固定代码,效果很好:)

#include "sharedmemoryringbuffer.h"
#include <QDebug>
#define DEBUGGINGNAME "[SharedMemoryRingbuffer]"

SharedMemoryRingBuffer::SharedMemoryRingBuffer(QString sharedMemoryName, int32_t size, QObject *parent) : QObject(parent)
{
    int sizeOfData = sizeof(int32_t) * (size);
    int sizeOfHeader = sizeof(SharedMemoryAttributes);
    _sharedMemory = new QSharedMemory(sharedMemoryName);

    if (_sharedMemory->isAttached()) _sharedMemory->detach();
    if (!_sharedMemory->attach()) {
        _sharedMemory->lock();
        _attributes = reinterpret_cast<SharedMemoryAttributes*>(_sharedMemory->data());
        _attributes->readPosition = 0;
        _attributes->writePosition = 0;
        _attributes->size = size;
        _sharedMemory->unlock();

        if (!_sharedMemory->create(sizeOfData+sizeOfHeader, QSharedMemory::ReadWrite )) {
            qDebug() << DEBUGGINGNAME << "Could not create shared memory object, aborting ...";
            qDebug() << DEBUGGINGNAME << _sharedMemory->errorString();
            //TODO: exit call
            return;
        }
    }

    _attributes->data = (int32_t*) _sharedMemory->data() + sizeOfHeader;

}

SharedMemoryRingBuffer::~SharedMemoryRingBuffer()
{
    _sharedMemory->detach();
    delete _sharedMemory;
}

int SharedMemoryRingBuffer::write(int32_t frame)
{
    _sharedMemory->lock();
    if ( !isFull() ) {
        _attributes->data[writePosition()] = frame;
        if (writePosition() + 1 >= _attributes->size) _attributes->writePosition = 0;
        else _attributes->writePosition += 1;
        _sharedMemory->unlock();
        return 1;
    }
    _sharedMemory->unlock();
    return 0;
}


/**
 * @brief SharedMemoryRingBuffer::read
 * @return
 * if the buffer is empty this functions return the last readable value
 *
 */
int32_t SharedMemoryRingBuffer::read()
{
    _sharedMemory->lock();
    int32_t frame = _attributes->data[readPosition()];
    if ( readPosition() != writePosition() ) {
        if (readPosition() + 1 >= _attributes->size ) _attributes->readPosition = 0;
        else _attributes->readPosition += 1;
        emit readFrame(_sharedMemory->key());
    }
    _sharedMemory->unlock();
    return frame;
}

int32_t SharedMemoryRingBuffer::length()
{
    if(readPosition() <= writePosition()) {
        return writePosition() - readPosition();
    } else {
        return readPosition() - writePosition();
    }
}

int32_t SharedMemoryRingBuffer::readPosition()
{
    return _attributes->readPosition;
}

int32_t SharedMemoryRingBuffer::writePosition()
{
    return _attributes->writePosition;
}

int SharedMemoryRingBuffer::avaibleSize()
{
    return -1;
}

int SharedMemoryRingBuffer::isEmpty()
{
    if ( readPosition() == writePosition() ) return 1;
    else return 0;
}

void SharedMemoryRingBuffer::empty()
{

}

int SharedMemoryRingBuffer::isFull()
{
    if ((writePosition() + 1) % _attributes->size == readPosition()) return 1;
    else return 0;
}