Skip to main content

C++ - inheriting ostream crashes on android but not windows



I have implemented a simple ostream and streambuf class. For some reason, it crashes when I try to instantiate my AndroidLogOStream object.





Note: I have stlport_static in my Application.mk







class AndroidLogStreamBuf : public std::streambuf

{

public:

inline AndroidLogStreamBuf() : std::streambuf()

{

//std::cout << "asdfg";



}



inline ~AndroidLogStreamBuf()

{



}







};



class AndroidLogOStream : public std::ostream

{

public:

inline AndroidLogOStream() : std::ostream(&mBuf)

{



}



inline ~AndroidLogOStream()

{



}



private:

AndroidLogStreamBuf mBuf;

};







It's barebones, and it runs fine on windows. It compiles fine on android, but it crashes for some reason. The last line it tries to execute is in _streambuf.c:46:







template <class _CharT, class _Traits>

locale

basic_streambuf<_CharT, _Traits>::pubimbue(const locale& __loc) {

this->imbue(__loc); <---- crash

locale __tmp = _M_locale;

_M_locale = __loc;

return __tmp;

}







Granted I am still quite confused on iostreams, but it must be something wrong with the constructor, I suppose it is not valid?


Comments

  1. In a constructor, the base class is initialized first, followed by all of the members. When you call the base class constructor std::ostream, you're passing it the address of mBuf, which has not yet been constructed. Accessing an object that hasn't yet been constructed has undefined behaviour.

    To get around this, you could redesign your classes as follows:

    class AndroidLogStreamBuf : public std::streambuf
    {
    public:
    AndroidLogStreamBuf() : std::streambuf()
    { }

    ~AndroidLogStreamBuf()
    { }
    };

    class AndroidLogOStream : public std::ostream
    {
    public:
    AndroidLogOStream(AndroidLogStreamBuf *buf) :
    std::ostream(buf),
    mBuf(buf)
    { }

    ~AndroidLogOStream()
    { }

    private:
    AndroidLogStreamBuf *mBuf;
    };

    class AndroidLogOStreamWithBuf
    {
    private:
    AndroidLogStreamBuf mBuf;
    AndroidLogOStream mStream;

    public:
    AndroidLogOStreamWithBuf() :
    mBuf(&mStream),
    mStream()
    { }

    virtual ~AndroidLogOStreamWithBuf()
    { }

    AndroidLogOStream& getOStream()
    {
    return mStream;
    }
    };


    Notice the order I've declared mBuf and mStream in AndroidLogOStreamWithBuf: the two fields will be initialized in that order, regardless of the order they appear in the constructor initializer list. As an aside, marking the member functions as inline in your original code was superfluous: when you define a member function within the class definition, it's automatically marked as inlinable.

    Whether this is a sensible design for your system depends on how you're intending to use these classes, but the answer is probably "no".

    ReplyDelete
  2. As was pointed out, the base class is constructed first and from the looks of it, the base class constructor seems to do something. I don't think it is meant to but the base class destructor would also create a problem and that will call pubsync() on the stream buffer.

    Of course, this explains the problem but doesn't provide a solution: the solution to this initialization problem is to make the the stream buffer (or a custom class containing the stream buffer as member) a virtual base class:

    class oandroidligstream:
    virtual AndroidLogStream,
    public std::ostringstream {
    ...
    }
    };


    the reason the base has to be virtual is that the stream buffer is an argument to the virtual base std::ios. To make sure your stream buffer is initialized first it has to be the left-most virtual base.

    ReplyDelete

Post a Comment

Popular posts from this blog

Why is this Javascript much *slower* than its jQuery equivalent?

I have a HTML list of about 500 items and a "filter" box above it. I started by using jQuery to filter the list when I typed a letter (timing code added later): $('#filter').keyup( function() { var jqStart = (new Date).getTime(); var search = $(this).val().toLowerCase(); var $list = $('ul.ablist > li'); $list.each( function() { if ( $(this).text().toLowerCase().indexOf(search) === -1 ) $(this).hide(); else $(this).show(); } ); console.log('Time: ' + ((new Date).getTime() - jqStart)); } ); However, there was a couple of seconds delay after typing each letter (particularly the first letter). So I thought it may be slightly quicker if I used plain Javascript (I read recently that jQuery's each function is particularly slow). Here's my JS equivalent: document.getElementById('filter').addEventListener( 'keyup', function () { var jsStart = (new Date).getTime()...

Is it possible to have IF statement in an Echo statement in PHP

Thanks in advance. I did look at the other questions/answers that were similar and didn't find exactly what I was looking for. I'm trying to do this, am I on the right path? echo " <div id='tabs-".$match."'> <textarea id='".$match."' name='".$match."'>". if ($COLUMN_NAME === $match) { echo $FIELD_WITH_COLUMN_NAME; } else { } ."</textarea> <script type='text/javascript'> CKEDITOR.replace( '".$match."' ); </script> </div>"; I am getting the following error message in the browser: Parse error: syntax error, unexpected T_IF Please let me know if this is the right way to go about nesting an IF statement inside an echo. Thank you.