2013-07-27 2 views
1

Я делаю межпроцессную связь между двумя моими процессами с boost :: interprocess :: message_queue.Boost IPC Message_Queue try_receive throws interprocess_exception :: library_error

Это первый раз, когда я использую его, поэтому это исключение не ясно для меня, потому что я не могу найти на нем никакой документации.

У меня есть мои настройки классов следующим образом:

struct Pos{float X,Y,Z;}; 
struct Quat{float 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 (Align структуры/классы для выравнивания 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; 
     } 
    } 
} 

Приложение продолжает выдавать «повышение :: interprocess_exception :: library_error» в блоке, где try_receive используется.

Что я делаю неправильно в этом случае? Я уверен, что передача данных одинакового размера, потому что 1) я использую тот же заголовок и 2) компилирую с теми же параметрами.

Я подтвердил, что переменные размеры одинаковы со следующим кодом в обеих программах:

MessageBox(NULL,string_format(
"Pos(%d):Quat(%d):NPCDataFoot(%d):NPCDataVehicle(‌​%d):ExchangeData(%d)", 
sizeof(Pos),sizeof(Quat),sizeof(NPCDataFoot),sizeof(NPCData‌Vehicle),sizeof(ExchangeData)).c_str() 
,"Reported sizes Client",0); 

Edit: я, кажется, есть «решить» это .. magicly;

Кажется, что этот код был ошибкой:

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 первый записывает размер сообщения в «вне» параметра recvd_size (ссылка на unused в коде), затем записывает приоритет «из» параметра priority (также ссылка на unused в коде - таким образом, эффективно перезапись recvd_size с величиной priority). Непосредственно ниже, вызов memcpy использует теперь неправильный recvd_size, что приводит к поведению, которое вы наблюдаете (неполная копия или переполнение буфера, в зависимости от priority).

Возможно, автор библиотеки должен был использовать оригинал top_msg->len (вместо параметра «out» recvd_size) для memcpy bytecount. Однако, чтобы избежать подобных сюрпризов, всегда используйте разные переменные для параметров «out» (назовите их unused1 и unused2, если вы этого желаете).

1

Это, скорее всего, вызвано использованием /zp1. Ваша программа и библиотеки, на которые она ссылается, будут думать, что структуры имеют разные размеры и/или местоположения участников. Не делай этого.

+0

Размеры кажутся одинаковыми: http: // 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(), «Сообщаемые размеры клиента», 0); ') – Gizmo

Смежные вопросы