【问题标题】:CRTP with unique_ptr causes segfault具有 unique_ptr 的 CRTP 导致段错误
【发布时间】:2018-08-27 22:49:18
【问题描述】:

我正在使用 CRTP 设计模式为我的项目实现日志记录机制。基本 CRTP 类如下所示:

#include <fstream>
#include <memory>
#include <mutex>
#include <iostream>
#include <sstream>

template <typename LogPolicy>
class Logger
{
  public:
    template <typename... Args>
    void operator()(Args... args)
    {
        loggingMutex.lock();
        putTime();
        print_impl(args...);
    }

    void setMaxLogFileSize(unsigned long maxLogFileSizeArg)
    {
        //if (dynamic_cast<FileLogPolicy *>(policy.get()))
        //    policy->setMaxLogFileSize(maxLogFileSizeArg);
    }

    ~Logger()
    {
        print_impl(END_OF_LOGGING);
    }

  protected:
    std::stringstream buffer;
    std::mutex loggingMutex;
    std::string d_time;
  private:
    static constexpr auto END_OF_LOGGING = "***END OF LOGGING***";

    void putTime()
    {
        time_t raw_time;
        time(&raw_time);
        std::string localTime = ctime(&raw_time);
        localTime.erase(std::remove(localTime.begin(), localTime.end(), '\n'), localTime.end());
        buffer << localTime;
    }

    template <typename First, typename... Rest>
    void print_impl(First first, Rest... rest)
    {
        buffer << " " << first;
        print_impl(rest...);
    }

    void print_impl()
    {
        static_cast<LogPolicy*>(this)->write(buffer.str());
        buffer.str("");
    }
};

其中一个具体的日志记录类是记录到文件,如下所示:

#include "Logger.hpp"

class FileLogPolicy : public Logger<FileLogPolicy>
{
  public:
    FileLogPolicy(std::string fileName) : logFile(new std::ofstream)
    {
        logFile->open(fileName, std::ofstream::out | std::ofstream::binary);
        if (logFile->is_open())
        {
            std::cout << "Opening stream with addr " << (logFile.get()) << std::endl;
        }
    }

    void write(const std::string content)
    {

        std::cout << "Writing stream with addr " << (logFile.get()) << std::endl;
        (*logFile) << " " << content << std::endl;
        loggingMutex.unlock();
    }

    virtual ~FileLogPolicy()
    {
    }

  private:
    std::unique_ptr<std::ofstream> logFile; //Pointer to logging stream
    static const char *const S_FILE_NAME;   //File name used to store logging
    size_t d_maxLogFileSize;         //File max size used to store logging
};

基本上,我创建策略类的对象并希望根据选择的策略记录内容。因此,例如我创建这样的记录器:

FileLogPolicy log("log.txt");

在这种情况下,它应该使用 Logger 通过调用 static_cast&lt;LogPolicy*&gt;(this)-&gt;write(buffer.str()) 将日志保存到文件中。显然调用 write 函数工作正常,但流对象正在更改为 null。如果还没有调用 FileLogPolicy 析构函数,那怎么可能呢?当我将 logFile 更改为普通指针时,一切正常。我不明白有什么不同。

【问题讨论】:

  • 为什么这么多人在写日志?
  • 有什么替代方案?
  • 使用现有的库?
  • 找伐木工?

标签: c++ c++14 crtp


【解决方案1】:
~Logger()
{
    print_impl(END_OF_LOGGING);
}

此代码在后代类被销毁后运行。

void print_impl()
{
    static_cast<LogPolicy*>(this)->write(buffer.str());
    buffer.str("");
}

然后它将this 转换为指向this 不再是的类的指针。

唯一ptr没了,连访问成员都是UB。

【讨论】:

  • 感谢您的回答。我不知道我是怎么错过的。
猜你喜欢
  • 1970-01-01
  • 2013-09-16
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 2017-04-17
  • 1970-01-01
  • 1970-01-01
  • 2015-09-03
相关资源
最近更新 更多