Archived

This forum has been archived. Please start a new discussion on GitHub.

Ice::OutputStream::writeTypeId bug

It seems that code like:
Ice::OutputStreamPtr out = Ice::createOutputStream(some_communicator);

out->writeTypeId("::My::SomeObject");

causes segmentation fault, so does this one:
Ice::OutputStreamPtr out = Ice::createOutputStream(some_communicator);

out->startEncapsulation();
out->writeTypeId("::My::SomeObject");
out->endEncapsulation();

In first case the problem is in IceInternal::BasicStream::writeTypeId:
TypeIdWriteMap::const_iterator k = _currentWriteEncaps->typeIdMap->find(id);

_currentWriteEncaps is NULL, as I understand in should be lazy intialized and
startEncapsulation does the job, but not completly, in IceInternal::BasicStream::startWriteEncaps:
        if(!oldEncaps) // First allocated encaps?
        {
            _currentWriteEncaps = &_preAllocatedWriteEncaps;
        }

but _preAllocatedWriteEncaps is just an instance of IceInternal::WriteEncaps where typeIdMap member is NULL that's why that segmentation fault happens.
The only place where typeIdMap and other members of _currentWriteEncaps get initialized is IceInternal::BasicStream::write(const ObjectPtr&), but
I don't want to send objects this way, I need to do it manually, any workaround for this ?

Comments

  • benoit
    benoit Rennes, France
    Hi,

    This method is only supposed to be used when marshalling an object and the code doesn't expect it to be called for another purpose. That being said, an exception would be nicer than a crash :) We'll fix this!

    Why do you want to use writeTypeId here? Can't you just encode the type as a string?

    Cheers,
    Benoit.
  • The problem is: I need to pass a class to some method using dynamic Ice and all I know about that class is it's type id, it's members and their types, so I want to be able to write like this:
    outStream->writeTypeId("::My::SomeObject")
    outStream->startSlice();
    outStream->writeInt(100);
    outStream->writeByte(10);
    outStream->endSlice();
    
    i.e pass an object of type:
    namespace My
    {
    class SomeObject
    {
    int a;
    byte b;
    }
    }
    
    I really need to do this using dynamic Ice, I'm able to pass simple types via ice_invoke and I should be able to pass classes using ice_invoke as well I guess...
  • benoit
    benoit Rennes, France
    You can't write the object directly to the stream. Usually, to marshall an object the easiest is to use the generated code helper functions (the "My::ice_writeSomeObject" method in your example).

    If your program doesn't have access to the generated code, you can implement an Ice::ObjectWritter wrapper and call writeObject with this wrapper. The Ice::ObjectWriter write method will be called when its time to marshal the object (this occurs when you call writePendingObjects on the streaming interface). E.g.:
    // C++
    
    class SomeObjectWriter : public Ice::ObjectWriter
    {
        virtual void write(const OutputStreamPtr& outStream) const
        {
            outStream->writeTypeId("::My::SomeObject")
            outStream->startSlice();
            outStream->writeInt(100);
            outStream->writeByte(10);
            outStream->endSlice();
        }
    };
    
    
    outStream->writeObject(new SomeObjectWriter); // Insert the object into the stream.
    
    ...
    outStream->writePendingObjects();
    ...
    
    

    See here in the Ice manual for more information.

    Cheers,
    Benoit.
  • Great, just what I need, thanks a lot !!!