我已经实现了一个简单的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;
}
当然,我仍然对iostream很困惑,但构造函数一定有问题,我认为它无效?
答案 0 :(得分:5)
在构造函数中,首先初始化基类,然后是所有成员。当您调用基类构造函数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;
}
};
请注意我在mBuf
中声明mStream
和AndroidLogOStreamWithBuf
的顺序:这两个字段将按此顺序初始化,无论它们出现在构造函数初始值设定项列表中的顺序如何。另外,在原始代码中将成员函数标记为inline
是多余的:当您在类定义中定义成员函数时,它会自动标记为无限。
这对你的系统来说是否合理,取决于你打算如何使用这些类,但答案可能是“不”。
答案 1 :(得分:1)
正如所指出的那样,首先构造基类,从它的外观来看,基类构造函数似乎做了一些事情。我不认为这是有意义的,但是基类析构函数也会产生问题,并且会在流缓冲区上调用pubsync()
。
当然,这解释了问题,但没有提供解决方案:此初始化问题的解决方案是使流缓冲区(或包含流缓冲区的自定义类作为成员)为virtual
库类:
class oandroidligstream:
virtual AndroidLogStream,
public std::ostringstream {
...
}
};
基础必须是虚拟的原因是流缓冲区是虚拟基础std::ios
的参数。为了确保首先初始化流缓冲区,它必须是最左边的虚拟基础。