Boost IPC Message_Queue try_receive 抛出 interprocess_exception::library_error
Posted
技术标签:
【中文标题】Boost IPC Message_Queue try_receive 抛出 interprocess_exception::library_error【英文标题】:Boost IPC Message_Queue try_receive throws interprocess_exception::library_error 【发布时间】:2013-07-27 17:50:11 【问题描述】:我正在使用 boost::interprocess::message_queue 在我的两个进程之间进行进程间通信。
这是我第一次使用它,所以我不清楚这个异常,因为我找不到任何文档。
我的课程设置如下:
struct Posfloat X,Y,Z;;
struct Quatfloat W,X,Y,Z;;
typedef unsigned char Byte;
struct NPCDataFoot
//some Pos and Quat variables here too
unsigned short AnimationIndex;
void Apply(NPCDataFoot &data)AnimationIndex=data.AnimationIndex;
NPCDataFoot()AnimationIndex=0;
;
struct NPCDataVehicle
//many many more
unsigned short lrAnalog;
void Apply(NPCDataVehicle &data)lrAnalog=data.lrAnalog;
NPCDataVehicle()lrAnalog = 0;
;
enum TransmissionDataType
TDT_NewNPC,//many more...
;
const unsigned short QueueMaxSize = 256;
struct ExchangeData
unsigned short CommandType;
unsigned short NPCPlayerID;
Byte State;
NPCDataFoot OnFootData;
NPCDataVehicle InCarData;
float MoveSpeed;
Pos MoveToPos;
//206
ExchangeData(unsigned short CommandType = 0, unsigned short NPCPlayerid = 0xFFFF)
: CommandType(CommandType), NPCPlayerID(NPCPlayerid)
ExchangeData(unsigned short CommandType, unsigned short NPCPlayerid, NPCDataFoot& foot_data, NPCDataVehicle& car_data)
: CommandType(CommandType), NPCPlayerID(NPCPlayerid), OnFootData(foot_data), InCarData(car_data)
;
我的两个程序都设置为使用 /zp1 标志进行编译(将结构/类对齐到 1 字节对齐)。
现在每当我到达此代码时:
ServerMsgQueue * message_queue = NULL;
PLUGIN_EXPORT void PLUGIN_CALL
ProcessTick()
static bool init = false;
static ExchangeData DataTransmision;
if(!init)
try
ServerMsgQueue = new message_queue(open_or_create
,string_format("REMOTESHAREDMEMORYBTWNPRCS%04x",GetServerVarAsInt("port")).c_str()
,1024 * QueueMaxSize,sizeof(ExchangeData));
catch(interprocess_exception &ex)
std::cout << ex.what() << ":" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << std::endl;
init = true;
static unsigned int unused;
if(ServerMsgQueue)
try
if(ServerMsgQueue->try_receive(&DataTransmision,sizeof(ExchangeData),unused,unused))
switch(DataTransmision.CommandType)
//some cases
default:std::cout << "UNKNOWN RECEIVED DATA!!!" << std::endl;break;
catch(interprocess_exception &ex)
//this happens always
std::cout << ex.what() << ":" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << std::endl;
应用程序在使用try_receive
的块中不断发出“boost::interprocess_exception::library_error”。
在这种情况下我做错了什么?我确定发送的数据大小相同,因为 1)我使用相同的标头和 2)我使用相同的选项进行编译。
我已确认变量大小与两个程序中的以下代码相同:
MessageBox(NULL,string_format(
"Pos(%d):Quat(%d):NPCDataFoot(%d):NPCDataVehicle(%d):ExchangeData(%d)",
sizeof(Pos),sizeof(Quat),sizeof(NPCDataFoot),sizeof(NPCDataVehicle),sizeof(ExchangeData)).c_str()
,"Reported sizes Client",0);
编辑:我似乎已经“解决”了它……神奇地;
看来这个代码是错误的:
static unsigned int unused;
if(ServerMsgQueue->try_receive(&DataTransmision,sizeof(ExchangeData),unused,unused))
改成
unsigned int Priority;
size_t sizexxx;
if(ServerMsgQueue->try_receive(&DataTransmision,sizeof(ExchangeData),sizexxx,Priority))
有人能解释为什么这行得通而其他代码不行吗?
【问题讨论】:
【参考方案1】:查看message_queue::do_receive
的源代码(从message_queue::try_receive
调用); do_receive
首先将消息大小写入“out”参数recvd_size
(在您的代码中引用unused
),然后将优先级写入“out”参数priority
(也是 在您的代码中引用unused
——从而有效地用priority
值覆盖recvd_size
)。紧接着,对memcpy
的调用使用了现在不正确的recvd_size
,导致您观察到的行为(不完整的复制或缓冲区溢出,取决于priority
)。
可以说,库的作者应该使用原始的top_msg->len
(而不是“out”参数recvd_size
)作为memcpy
字节数。但是,为了避免这些意外,请始终为“out”参数使用不同的变量(如果您愿意,可以将它们称为 unused1
和 unused2
)。
【讨论】:
【参考方案2】:这很可能是由于您使用了/zp1
而引起的。您的程序及其链接的库会认为结构具有不同的大小和/或成员位置。不要那样做。
【讨论】:
大小似乎相同:imgur.com/Ww5I7YW(使用以下代码:MessageBox(NULL,string_format("Pos(%d):Quat(%d):NPCDataFoot(%d):NPCDataVehicle(%d):ExchangeData(%d)",sizeof(Pos),sizeof(Quat),sizeof(NPCDataFoot),sizeof(NPCDataVehicle),sizeof(ExchangeData)).c_str(),"Reported sizes Client",0);
)以上是关于Boost IPC Message_Queue try_receive 抛出 interprocess_exception::library_error的主要内容,如果未能解决你的问题,请参考以下文章
boost::interprocess::message_queue 权限被拒绝
boost::interprocess::message_queue 必须由写入它的进程创建?