我用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;
}
答案 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;
}