为什么使用带有std :: cout重定向的boost :: posix_time :: time_facet,最终会抛出bad_cast?

时间:2017-09-07 13:50:57

标签: android c++ qt boost

我有一个基于CPPUNIT库的测试程序和运行~900单元测试的Qt。该程序使用QtCreator部署在Android上。它与~80个库相连,每个库都定义了一些测试。

代码更改后,由于std::bad_cast被抛出,测试程序开始崩溃。

原始代码(无bad_cast):

class TimeUnit
{
    friend std::ostream& operator<<(std::ostream &os, const TimeUnit& var);
public:

    std::string TimeUnit::toString() const
    {
        std::stringstream stream;
        static std::string facetStr = "%Y/%m/%d %H:%M";

        stream.imbue(std::locale(std::locale::classic(), new boost::posix_time::time_facet(facetStr.c_str())));
        stream << *m_time;
        return stream.str();
    }
private:
    boost::posix_time::ptime m_time;
};

std::ostream& operator<<(std::ostream &os, const TimeUnit& var)
{
    os << var.toString();
    return os;
}

新代码(让测试程序在某些时候抛出bad_cast):

class TimeUnit
{
    friend std::ostream& operator<<(std::ostream &os, const TimeUnit& var);
public:

    std::string TimeUnit::toString() const
    {
        std::stringstream stream;
        stream << *this;
        return stream.str();
    }
private:
    boost::posix_time::ptime m_time;
};

std::ostream& operator<<(std::ostream &os, const TimeUnit& var)
{
    static std::string facetStr = "%Y/%m/%d %H:%M";

    os.imbue(std::locale(std::locale::classic(), new boost::posix_time::time_facet(facetStr.c_str())));
    // this next line ends up throwing std::bad_cast!
    os << *(var.m_time);
    return os;
}

我的std::bad_cast会在某个时刻抛出新代码operator<<异常。根据{{​​3}}:

  

当dynamic_cast引用时,抛出此类型的异常   类型未通过运行时检查(例如,因为类型不相关   通过继承),以及来自std :: use_facet的请求方面   在语言环境中不存在。

... operator<< boost::posix_time::ptime use_facet std::cout ...

经过大量调查后,我可以得出结论:

  • 崩溃是特定于Android的(Window完全可以正常工作)
  • 这是由于将一个方面附加到std::stringstream(在新代码中,如果我创建一个本地os << str.str()将方面应用于它,稍后将结果复制为os.imbue(std::locale(std::locale::classic(),...),否更多崩溃)
  • os.imbue(std::locale(os.getloc(),...))os.imbue都会导致同样的崩溃
  • 删除os.imbue(std::locale::classic());电话会使崩溃消失
  • 从我的operator<<返回之前致电operator<<无法解决问题

不幸的是,我试图在MCVE中隔离问题,但无法用一些更基本的代码重现问题......

所以我的问题是(是):

  • 我在bad_cast
  • 中做错了什么
  • 为什么此代码可以在Windows上运行并在Android上崩溃?这可能是由于疯狂的C ++运行时会以错误的方式删除构面吗?

修改

经过一些调查后,我发现如果我将std::cout重定向到我的主文件,只会抛出class ScopedRedirect { public: ScopedRedirect(std::ostream & inOriginal, std::ostream & inRedirect) : mOriginal(inOriginal), mOldBuffer(inOriginal.rdbuf(inRedirect.rdbuf())) {} virtual ~ScopedRedirect() { mOriginal.rdbuf(mOldBuffer); } ScopedRedirect(const ScopedRedirect&) = delete; ScopedRedirect& operator=(const ScopedRedirect&) = delete; protected: std::ostream & mOriginal; std::streambuf * mOldBuffer; }; int main( int argc, char* argv[] ) { std::fstream output( "cout.txt", std::ios_base::out ); assert( output.is_open() ); ScopedRedirect redirectCount( std::cout, output ); ... } ,使用:

springProperty

0 个答案:

没有答案