5

以下の最初のコードスニペット(GenericMessage.hxxで定義)に示されているGenericMessageという名前のクラスがあります。

ZMQキューを介してクラスGenericMessageのインスタンスを送信しようとするTestFE.cppという名前の.cppファイル(以下の2番目のコードスニペットを参照)があります(非常に下の4番目のコードスニペット-ZmqHandler.hxxも参照)。TesfFE.cppは、ZmqHandler.hxxを含めることにより、ここでZMQプッシュパターンを実装します。

ZMQキューを介して前述のGenericMessageインスタンスを受信するTestBE.cppという名前の別の.cppファイル(以下の3番目のコードスニペットを参照)があります。TestBE.cppは、ここでZMQプルパターンを実装して、ZMQキューを介してGenericMessageインスタンスを取得します。

TestFE.cppでは、GenericMessageオブジェクトをZMQキューで受け入れることができる形式に変換するために、標準のmemcpy関数を使用しています。TestBE.cppの21行目(コメントの3番目のコードスニペットでマークされています)では、送信側であるTestFE.cppでmemcpyが正しく機能していないように見えるため、セグメンテーション違反が発生します。TestBEを実行すると、以下のメッセージが表示されます。また、すぐ下にgdbバックトレースを提供しています。ここで何が問題なのか教えていただけますか?memcpyが私のGenericMessageオブジェクトをZMQmessage_t形式に正しくコピーできないのはなぜだと思いますか?それとも、問題は他にあると思いますか?コメントをいただければ幸いです。

エラーメッセージ

  $ ./TestBE
  Connecting to FE...
  RECEIVED: 1
  Segmentation fault (core dumped)

GDBバックトレース

  (gdb) r
   Starting program: /home/holb/HOLB_DESIGN/ZMQ/WORK1/TestBE 
  [Thread debugging using libthread_db enabled]
  Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
  [New Thread 0xb7c84b40 (LWP 4252)]
  [New Thread 0xb7483b40 (LWP 4253)]
  Connecting to FE...
  RECEIVED: 1

  Program received signal SIGSEGV, Segmentation fault.
  0xb7f371cc in std::basic_string<char, std::char_traits<char>, std::allocator<char>       >::basic_string(std::string const&) ()
  from /usr/lib/i386-linux-gnu/libstdc++.so.6
  (gdb) bt
  #0  0xb7f371cc in std::basic_string<char, std::char_traits<char>,      std::allocator<char> >::basic_string(std::string const&) ()
  from /usr/lib/i386-linux-gnu/libstdc++.so.6
  #1  0x08049621 in GenericMessage<std::string>::getData (this=0xbffff06c)
  at GenericMessage.hxx:18
  #2  0x08049075 in main () at TestBE.cxx:21
 (gdb) 

CODE SNIPPET 1(GenericMessage.hxx) #include #include #include

  template <class T>
  class GenericMessage {
  public:

         GenericMessage(int id, T msg): 
         beId(id), 
         data(msg)
         {}

         ~GenericMessage(){}

         T getData()
         {
           //LINE 18 is the following line!
           return data;
         }

          std::string toString()
          {
              std::ostringstream ss;
              ss << getBeId();
              std::string ret =  ss.str();

              return ret;
          }

          void setBeId(int id)
          {
              beId = id;
          }

          int getBeId()
          {
             return beId;
          }
 private:
        int beId;
        T data;
 };

CODE SNIPPET 2(TestFE.cxx ==>送信者) #include "ZmqHandler.hxx" // ZmqHandler.hxxのコンテンツについては、下部にある4番目のスニペットを参照してください

 int main ()
 {
     ZmqHandler<std::string> zmqHandler;
     int counter = 1;

     while(1)
     {  
        std::string data = "Hello there!\0";
        GenericMessage<std::string> msg(counter, data);
        zmqHandler.sendToBE(&msg);
        counter++;
        sleep(1);
     }

     return 0;
 }

CODE SNIPPET 3(TestBE.cxx ==>レシーバー)

  #include "zmq.hpp"
  #include "GenericMessage.hxx"
  #include <string>
  #include <iostream>

  int main ()
  {
      //  Prepare our context and socket
      zmq::context_t context (1);
      zmq::socket_t socket (context, ZMQ_PULL);

     std::cout << "Connecting to FE..." << std::endl;
     socket.connect ("tcp://localhost:5555");

    while(1){
        zmq::message_t reply;
            socket.recv (&reply);
            GenericMessage<std::string> *msg = (GenericMessage<std::string>*)(reply.data());                
            std::cout << "RECEIVED: " << msg->toString() << std::endl;

           /* *********************************  */
           /*  SEGMENTATION FAULT HAPPENS HERE   */
           /* The member "data" in class GenericMessage cannot be received while the  member "id" in the previous line can be received. */
           std::cout << "DATA: " << ((std::string)msg->getData())  << std::endl;
           /* ********************************** */
     }

     return 0;
 }

コードスニペット4(ZMQHandler.hxx)

  #include "zmq.hpp"  
  #include "GenericMessage.hxx"
  #include <pthread.h>
  #include <unistd.h>
  #include <cassert>

  template <class T>
  class ZmqHandler {
  public:
        ZmqHandler():
    mContext(1),
    mOutbHandlerSocket(mContext, ZMQ_PUSH)
        {    
          mOutbHandlerSocket.bind ("tcp://*:5555");       
        }

       ~ZmqHandler() {}

       void *sendToBE(GenericMessage<T> *theMsg)
       {
         //  Place the new request to the zmq queue for BE consumption
         zmq::message_t msgToSend(sizeof(*theMsg));

         memcpy ( msgToSend.data(), ((GenericMessage<T>*)theMsg), sizeof(*  ((GenericMessage<T>*)theMsg)));

         mOutbHandlerSocket.send(msgToSend);

         std::cout << "SENT request: [" << theMsg->toString() << "]" << std::endl;

         return (NULL);
        }   

   private:  
        zmq::context_t mContext;
        zmq::socket_t mOutbHandlerSocket; 

};
4

1 に答える 1

5

私は問題を見始めています。ポインタ()を持つメンバー変数を含む完全な「構造」を送信することですstd::string。ポインタはそれらを作成したプログラムでのみ有効であるため、これを行うことはできません。

構造を送信する前にシリアル化してから、受信側で逆シリアル化する必要があります。

このためのBoostシリアル化Googleプロトコルバッファ、またはその他の数のライブラリなどのライブラリを使用できます。

于 2013-01-21T11:49:02.633 に答える