Boost记录器在动态初始化器中初始化'不适用于widechar

时间:2016-11-25 10:16:34

标签: c++ c++11 boost

我试图编写一个类来包装Boost记录器以便记录widechar。

问题是如果Logger被定义为 const成员引用,那么它会抛出异常'无法转换字符编码',否则它可以正常工作。

我在Visual Studio C ++中的Logger构造函数中添加了一个断点,在' Call Stack'窗口,它显示呼叫由

启动
  

ConsoleApplication1.exe!`'记录器的动态初始化程序'()

所以问题是,如果定义为 const成员参考,会有什么不同?

这是一个最简单的例子:

#include "stdafx.h"
#include <iostream>

#include <boost/locale/generator.hpp>
#include <boost/log/common.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/trivial.hpp>

namespace logging = boost::log;
namespace sinks = boost::log::sinks;
namespace attrs = boost::log::attributes;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
namespace keywords = boost::log::keywords;

class Logger {
public:
    static const Logger& GetInstance() {
        static Logger logger;
        return logger;
    }

    void Log(const std::wstring& message) const {
        src::wseverity_logger< logging::trivial::severity_level > slg;
        BOOST_LOG_SEV(slg, logging::trivial::error) << message;
    }

private:
    Logger() {
        auto sink = logging::add_file_log(keywords::file_name = "sample.log");

        std::locale loc = boost::locale::generator()("en_US.UTF-8");
        sink->imbue(loc);

        logging::add_common_attributes();
    }
};

// *** The problem is introduced by line below ***
// *** If this line is removed, the logging doesn't throw exception. ***
const Logger& logger = Logger::GetInstance();

int main(int argc, char* argv[]) {
    try {
        Logger::GetInstance().Log(L"中文");
    }
    catch (const std::exception& e) {
        std::cout << e.what() << std::endl;
    }

    return 0;
}

1 个答案:

答案 0 :(得分:0)

问题基本上是static initialization order fiasco

记录器有两种可能的首次初始化:

const Logger& logger = Logger::GetInstance(); // <== (a)

int main(int argc, char* argv[]) {
    try {
        Logger::GetInstance().Log(L"中文");   // <== (b)

(b)发生在main之后,因此保证在所有pre main()初始化发生后运行。 (a)没有这样的保证,并且与其他潜在的静态初始化无关。似乎发生的事情是Logger::Logger()中的某些东西依赖于已经初始化的另一个对象 - 但这还没有发生。