我正在尝试使用boost的托管共享内存设置一个用于写入连续字节信息(int)的系统。这是我班级的精简版:
class PACKET_INFO
{
private:
offset_ptr<char> data[10]; // data pointers for various IPC threads to create transfer blocks.
public:
int Put(void * src,int to,int from,int type,int size); //write
bool message_sig; // Received message
int datasize;
int Get(void * dest,int ID); //Read
boost::interprocess::interprocess_mutex mutex;
};
int PACKET_INFO :: Put(void * src,int to,int size)
{
managed_shared_memory managed_shm(open_only, "SHM_test");
if(message_sig) return 0; //If there's already a message waiting, don't do anything
scoped_lock<interprocess_mutex> lock(mutex,try_to_lock);
if(!lock) return 0;
data[to] = (char *)managed_shm.allocate(size*sizeof(int));
memcpy(data[to].get(),src,size*sizeof(int));
message_sig = true;
datasize = size;
}
int PACKET_INFO :: Get(void * dest,int ID)
{
managed_shared_memory managed_shm(open_only, "SHM_test");
scoped_lock<interprocess_mutex> lock(mutex,try_to_lock);
if(!lock) std::cout << "Will fail to read!" << std::endl;
memcpy(dest,data[ID].get(),datasize*sizeof(int));
message_sig = false; //Reset after receiving.
datasize = 0;
managed_shm.deallocate(data[ID].get()); //release memory
}
我使用其他数据成员(未显示)在写入和接收数据之前执行完整性检查。一切都按计划进行。当两个并行进程(A和B)运行时,A总是创建托管共享内存对象“SHM_test”并使用Put函数将数据写入B.这是通过将所需大小分配给特定offset_ptr并对其执行memcpy来完成的。 。 B使用Get函数读取此数据,并相应地返回特定offset_ptr中的数据。
现在,只要我看到这些函数被两个常规的单独进程调用,这就完美无缺。但是,当我运行使用Put函数的A的线程版本时,它运行良好约29/30次。在某种程度上,我在进程B中遇到了一个段错误,指出了memcpy错误。关于B的进一步调试我得到了:
(gdb) print data[ID]
$8 = {internal = {m_offset = 18446744073690921056, alignment_helper = {data_ = {buf = "`\270\343\376\377\377\377\377",
align_ = {<No data fields>}}}}}
(gdb) print data[ID].get()
$9 = 0x7ffff346c3d0 <Address 0x7ffff346c3d0 out of bounds>
这表明offset_ptr的地址不在流程的合法范围内。为了满足,我同时调试了进程A:
(gdb) print Packet->data[ID]
$3 = {internal = {m_offset = 18446744073690921056, alignment_helper = {data_ = {buf = "`\270\343\376\377\377\377\377", align_ = {<No data fields>}}}}}
(gdb) print Packet->data[ID].get()
$4 = 0x7ffff3c293d0 ""
其中,Packet是PACKET_INFO类的对象。这个对象被进程A构建为共享内存中的命名对象,并由进程B在共享内存中找到。通过查看GDB的输出,偏移量明显匹配......意味着它应该可以工作!但我真的无法弄清楚为什么在线程进程A的情况下,这会导致进程B的offset_ptr超出界限。
我知道这是问题的一个非常简化的版本,但我希望它足以用于诊断或建议。
编辑:警告! 由于进程A的线程运行put函数并成功返回,因此我无法在线程点调试A. A的调试信息来自父进程。