-1

I have 2 different applications, a sender and a receiver. the Sender will send a message over to the receiver, who will decode the message and print to the console. However, I keep getting segmentation fault error.

Both sender and receiver application have the same TestContainer.h and TestContainer.cpp.

Casting method

template<class To,class From>To cast(From v)
{
        return static_cast<To>(static_cast<const void*>)(v);
}

Sender application

int main()
{
    TestContainer tc;
    tc.setDesc("this is a message");
    const char* castedData = cast<const char*>(&tc);

    const TestContainer test_tc = cast<const TestContainer*>(castedData);

    // i get back "this is a message",so the casting is working
    cout << "message content: " << test_tc->getDesc() <<endl;

    TaoSender;      
    TaoSender.send(castedData);     

    return 1;
}

Receiver Application

void push(const RtecEventComm::EventSet& events)
{
    const char* receivedData;
    events[0].data.any_value >>= receivedData;

    cout << "data received: " << receivedData << endl;

    const TestContainer rcv_tc = cast<const TestContainer*>(receivedData);

    cout << "message content: " << rcv_tc->getDesc() <<endl; // error(segmentation fault)
}

TestContainer.h and TestContainer.cpp

class TestContainer{
    public 
        TestContainer();
        virtual ~TestContainer();
        const std:string& getDesc () const {
            return desc;
        }
        void setDesc(const std::string& desc) {
            this->desc = desc;
        }
    private
        std::string desc;
}



#include TestContainer.h

TestContainer::TestContainer(){}
TestContainer::~TestContainer(){}

The value of castedData at the sender and the value of receivedData at the receiver is the same, so I guess the message sending is correct.

However,at the Receiver, after converting the receivedData buffer to a Testcontainer pointer and attempting to access the desc, I get a segmentation fault error.

I also tried casting back to Testcontainer in the Sender, and I am able to access the desc. So what did I miss out?

Tony Tony
  • 455
  • 1
  • 4
  • 9
  • 1
    You shouldn't cast the data, you cast a char* to a class, that is asking for problems. – Johnny Willemsen Nov 18 '16 at 08:58
  • This code has basic syntax errors eg `return static_cast(static_cast" and misplaced parentheses. Please post actual code in a self contained example ([MCVE]). – davmac Nov 18 '16 at 09:59
  • This doesn't look at all like a CORBA program, check the examples and tests that are part of TAO – Johnny Willemsen Nov 20 '16 at 09:53
  • @JohnnyWillemsen The TAO RtecEvent sending and receiving service is encapsulated by me, so if i send a simple string, float, or int value the receiver can receive the value perfectly,hence the messaging service is working. However, If i want to send a class (collection of attribute values), how should I send it? I do have over 40 classes,so I was hoping for an easy way to cast to a data stream. – Tony Tony Nov 21 '16 at 01:05
  • You have to put the data yourself into for example a CORBA Any and send that. You just can't cast a class, TAO doesn't know how to marshal your types into a wire representation. – Johnny Willemsen Nov 21 '16 at 07:42
  • Or define all types in IDL and updated your application code to use the IDL generated types. Your example does use std::string, something which is not supported by TAO but is supported by the IDL to C++11 language mapping (which is way easier). – Johnny Willemsen Nov 21 '16 at 10:20

1 Answers1

1

Although the code in your question contains errors, if I understand you correctly you are trying to push the representation of an object over a pipe or other channel to another process, where you reconstruct the object and try to use it.

You could do this with "Plain Old Data" objects, but the TestContainer class has virtual methods and therefore it is not POD. In most implementations of C++, objects of type TestContainer will contain a vtable pointer which refers to a table allocated within the process' address space. The address of this table will likely be different in different processes. Therefore, copying the representation of the TestContainer object byte-by-byte to another process will lead to crashes when you try to call a virtual method.

TestContainer instances also contain a std::string. A string allocates storage to hold the string contents and this storage will be outside the objecet itself. Transmitting the byte representation of the string as part of TestContainer results in reconstruction at the other end of a string that holds a pointer to a memory address in another process. Within the receiver, that memory address will refer to something else. Hence, the string will not be successfully reconstructed.

To send objects between processes you need to properly transmit them in a form that is independent of memory addresses contained within (whether that be a vtable pointer, a pointer member, or a pointer member of a an opaque member such as a string). The process of converting data to such a form is called serialization. There are libraries available to assist with this, but nothing in the standard library.

davmac
  • 20,150
  • 1
  • 40
  • 68