QSharedMemory创建和读取时返回大小不一致的原因及解决方法
大小不一致的原因
这个现象是操作系统层面的正常行为,不属于QSharedMemory的bug:
- 所有主流操作系统的共享内存分配最小单位都是内存页(默认大小通常为4096字节),你申请的大小如果不是页大小的整数倍,系统会自动向上对齐到最近的页大小整数倍。你遇到的数值刚好符合这个规则:658824 ÷ 4096 ≈ 160.85,向上取整161页,161×4096 = 659456,和你读取到的共享内存大小完全一致。
- 你提到的偶发大小正确的情况,是因为前次运行的共享内存段没有被正常释放,程序附着到了残留的旧共享内存段上,读取到了旧段的大小值,重启后系统清理了残留段,就会回到对齐后的正确大小。
你当前用空字符截断的临时方案风险很高:如果存储的是带\0的二进制数据(图片、序列化结构体等),会直接导致数据被异常截断,完全不可靠。
标准解决方案(非临时 workaround)
共享内存通信的通用规范是:在共享内存开头固定预留定长字节存储实际写入的数据长度,写入端先写长度再写业务数据,读取端先读长度字段再取对应长度的内容即可,完全不受系统页对齐的影响。
写入端修改示例
int dataSize = buffer->size(); // 总申请大小 = 长度字段大小(用定长类型quint32,避免跨架构位宽差异) + 实际业务数据大小 int totalApplySize = sizeof(quint32) + dataSize; if (!m_sharedMemory->create(totalApplySize)) { qCritical() << tr("Unable to create shared memory segment."); // 可选:创建失败时先尝试清理残留的旧共享内存段再重试创建 // if (m_sharedMemory->attach()) { m_sharedMemory->detach(); } 再重新调用create return; } m_sharedMemory->lock(); char *memStart = (char*)m_sharedMemory->data(); // 第一步:写入实际业务数据的长度 *reinterpret_cast<quint32*>(memStart) = dataSize; // 第二步:写入实际业务数据,偏移长度字段的大小 memcpy(memStart + sizeof(quint32), buffer->data(), dataSize); m_sharedMemory->unlock();
读取端修改示例
QSharedMemory sharedMemory(sharedMemoryName); if (!sharedMemory.attach(QSharedMemory::AccessMode::ReadOnly)) { qCritical() << "Unable to attach to shared memory segment."; return nullptr; } sharedMemory.lock(); const char *memStart = (const char*)sharedMemory.constData(); // 第一步:读取开头的长度字段,拿到真实业务数据的大小 quint32 realDataSize = *reinterpret_cast<const quint32*>(memStart); // 第二步:读取对应长度的业务数据即可 QByteArray realData(memStart + sizeof(quint32), realDataSize); sharedMemory.unlock(); // 后续直接使用realData即可,不需要关注共享内存的实际对齐后大小
内容的提问来源于stack exchange,提问作者Duesentrieb
相关产品推荐
相关产品推荐

