C + + – inheritanceandroid的ostream崩溃,但不是Windows

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

注意:我的Application.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; }; 

它是准系统,它在Windows上运行良好。 它在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的地址, 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; } }; 

注意我在mStream中声明了mBufmStreamAndroidLogOStreamWithBuf :两个字段将按照顺序进行初始化,无论它们在构造函数初始化列表中出现的顺序如何。 顺便说一下,在原始代码中将成员函数标记为inline是多余的:当您在类定义中定义成员函数时,它会自动标记为inlinable。

对于你的系统来说这是否是一个明智的设计取决于你打算如何使用这些类,但答案可能是“否”。

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

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

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

基地必须是虚拟的原因是流缓冲区是虚拟基地std::ios 。 为了确保你的流缓冲区被初始化,它必须是最左边的虚拟基地。