C++继承的ostream在android上崩溃,但在windows上没有

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

本文关键字:但在 windows 崩溃 C++ ostream android 继承      更新时间:2023-10-16

我实现了一个简单的ostream和streambuf类。出于某种原因,当我尝试实例化AndroidLogOStream对象时,它会崩溃。

注意:我的应用程序.mk 中有stlport_static

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;
    };

它光秃秃的,在窗户上运行良好。它在android上编译得很好,但由于某种原因崩溃了。它尝试执行的最后一行是_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;
}

当然,我对iostreams仍然很困惑,但它一定是构造函数出了问题,我想它是无效的?

在构造函数中,基类首先初始化,然后初始化所有成员。当您调用基类构造函数std::ostream时,您正在向它传递尚未构造的mBuf的地址。访问尚未构造的对象具有未定义的行为。

为了解决这个问题,你可以重新设计你的类如下:

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;
    }
};

注意我在AndroidLogOStreamWithBuf中声明的mBufmStream的顺序:这两个字段将按该顺序初始化,而不管它们在构造函数初始值设定项列表中的出现顺序如何。顺便说一句,在原始代码中将成员函数标记为inline是多余的:当您在类定义中定义成员函数时,它会自动标记为可内联。

对于您的系统来说,这是否是一个合理的设计取决于您打算如何使用这些类,但答案可能是"否"。

正如前面所指出的,基类是首先构造的,从外观上看,基类构造函数似乎做了一些事情。我不认为这是故意的,但基类析构函数也会产生问题,这将在流缓冲区上调用pubsync()

当然,这解释了问题,但并没有提供解决方案:这个初始化问题的解决方案是使流缓冲区(或包含流缓冲区作为成员的自定义类)成为virtual基类:

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

基必须是虚拟的原因是流缓冲器是虚拟基CCD_ 9的自变量。为了确保流缓冲区首先初始化,它必须是最左边的虚拟基础。

相关文章: