10

次のデータ構造があります。

typedef struct
{
    short id;
    string name;
    short age;
} person_struct;

ブースト メッセージ キューを使用して、このデータ構造を別のプロセスのメッセージ キュー受信者に送信しようとしました。ただし、受信後、上記の構造の「名前」変数にアクセスすると、セグメンテーション違反が発生します。

以下は私の送信者機能です:

person_struct MyRec;
MyRec.id = 1;
MyRec.name = "ABC123";
MyRec.age = 20;   
message_queue mqSender(create_only, "MSG_Q", 100, sizeof(person_struct));
mqSender.send(&MyRec, sizeof(person_struct), MQ_PRIORITY);

以下は私のレシーバー関数です:

message_queue myReceiver(open_only, "MSG_Q");
person_struct *recvMsg = new person_struct();
size_t msg_size;
unsigned int priority;
myReceiver.receive(recvMsg, sizeof(person_struct), msg_size, priority);
cout << "ID: " << (*recvMsg).id << endl;
cout << "Name: " << (*recvMsg).name << endl;
cout << "Age: " << (*recvMsg).age << endl;

(*recvMsg).id の cout は問題ありませんが、(*recvMsg).name の cout でセグメンテーション違反が発生しました。構造のシリアル化を行う必要があることをどこかで読んでくださいが、その方法がわかりません。誰でも提案できますか?

4

2 に答える 2

18

メッセージ キューのブースト ドキュメントから:

メッセージ キューは、プロセス間で raw バイトをコピーするだけで、オブジェクトを送信しません。これは、メッセージ キューを使用してオブジェクトを送信する場合、オブジェクトはバイナリ シリアル化可能でなければならないことを意味します。たとえば、プロセス間で整数を送信できますが、std::string は送信できません。プロセス間で複雑なデータを送信するには、Boost.Serialization を使用するか、高度な Boost.Interprocess メカニズムを使用する必要があります。

Boost.Serialization を使用してオブジェクトをシリアル化し、受信側で逆シリアル化します。

いくつかの簡単で実用的なコード:

info.hpp

#include <boost/serialization/string.hpp>

#define MAX_SIZE 1000

class info
{
    public:
        info (int i = 0, std::string n = "")
            : id(i), name(n)
        {};

        int id;
        std::string name;

    private:
        friend class boost::serialization::access;

        template<class Archive>
            void serialize(Archive & ar, const unsigned int version)
            {  
                ar & id;
                ar & name;
            }
};

send.cpp

#include <string>
#include <sstream>

#include <boost/interprocess/ipc/message_queue.hpp>
#include <boost/archive/text_oarchive.hpp>

#include "info.hpp"

using namespace boost::interprocess;

int main ()
{
    try
    {  
        message_queue mq
            (
             open_or_create,
             "mq",
             100,
             MAX_SIZE
            );

        info me(1, "asdf");

        std::stringstream oss;

        boost::archive::text_oarchive oa(oss);
        oa << me;

        std::string serialized_string(oss.str());
        mq.send(serialized_string.data(), serialized_string.size(), 0);
    }
    catch(interprocess_exception &ex)
    {  
        std::cerr << ex.what() << std::endl;
    }
}

受信.cpp

#include <string>
#include <iostream>

#include <boost/interprocess/ipc/message_queue.hpp>
#include <boost/archive/text_iarchive.hpp>

#include "info.hpp"

using namespace boost::interprocess;

int main ()
{
    try
    {  
        message_queue mq
            (
             open_only,
             "mq"
            );
        message_queue::size_type recvd_size;
        unsigned int priority;

        info me;

        std::stringstream iss;
        std::string serialized_string;
        serialized_string.resize(MAX_SIZE);
        mq.receive(&serialized_string[0], MAX_SIZE, recvd_size, priority);
        iss << serialized_string;

        boost::archive::text_iarchive ia(iss);
        ia >> me;

        std::cout << me.id << std::endl;
        std::cout << me.name << std::endl;
    }
    catch(interprocess_exception &ex)
    {  
        std::cerr << ex.what() << std::endl;
    }

    message_queue::remove("mq");
}
于 2012-09-10T10:30:01.670 に答える