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

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex