log4cpp:关于 SIGSEGV 的两个问题

log4cpp: two problems about SIGSEGV

我正在Linux下做一个cpp项目,我想建立一个日志系统,把一些重要的信息记录到一个文件中。所以我使用这个库:log4cpp

这是我关于 log4cpp 的代码:

// class Log head file
class Log
{
public:
    explicit Log(const char * infoCategory = nullptr, const string & pattern = string("%d: %p %c %x: %m%n"), const char * filename = "log")
    : category(infoCategory == nullptr ? Category::getRoot() : Category::getRoot().getInstance(infoCategory))
    {
        logFile.open(filename, ios::app);
        osAppender = new OstreamAppender("osAppender", &logFile);
        patternLayout = new PatternLayout();
        patternLayout->setConversionPattern(pattern);
        osAppender->setLayout(patternLayout);
        category.addAppender(osAppender);
        logFile.seekp(0, ios::end);
        size = logFile.tellp();
    }
    ~Log()
    {
        category.shutdown();
        logFile.close();
        // Do NOT delete osAppender and patternLayout
    }
    void info(const string & info)
    {
        category.info(info);
    }
private:
    ofstream logFile;
    streampos size;
    Category & category;
    OstreamAppender * osAppender;
    PatternLayout * patternLayout;
};

现在,我可以用Log写点东西了。比如有一个class这样的Agent:

#include "Log.h"
class Agent
{
public:
    ~Agent()
    {
        terminate();
    }
    void initialize()
    {
        log.info(" initialized.");
    }
    void terminate()
    {
        log.info(" terminated.");
    }
    static Agent & getInstance()
    {
        static Agent agent;
        return agent;
    }
    Agent()
    {
    }
private:
    Log log;
};

函数getInstance是生成"Singleton"。它的构造函数是私有的,所以我们必须调用 getInstance 来生成一个对象。由于这个对象是静态的,所以它只能初始化一次。 现在在main,我这样写:

int main()
{
    Agent & agent = Agent::getInstance();
    agent.initialize();
    return 0;
}

现在,如果我 运行 它,项目将停止在函数 Log::info 中,我将收到此错误:Signal received: SIGSEGV(Segmentation fault)
令我惊讶的是,如果我删除 log.info("terminated."); 或删除 log.info("initialized"); 或者我将两个 info 移动到函数 initializeterminate 中,错误会消失。
或者,如果我在函数 main 中初始化一个普通的 Agent,我的意思是我不使用 getInstance,而是这样做:Agent agent;,错误将消失也是。
或者,如果我在函数 getInstance 中新建一个 Agent,而不是使用 static,错误也会消失。
这是我的第一个问题。

我的第二个问题在这里:
请注意Log的析构函数中有注释:
// do NOT delete osAppender and patternLayout

我发表这样的评论是因为我认为它们都是来自new的指针,所以我可以而且应该删除它们。但是如果我删除其中一个或两个,我会得到同样的错误:
Signal received:SIGSEGV.

问题已解决。
我遇到这个问题是因为 logagent 这里都是静态的。
意思是在main函数中afterreturn 0;都会free,我们无法决定free的顺序
这样的话,显然在调用agent的虚函数之前,log已经空闲了,所以我在虚函数中调用terminate()的时候,就会报错[=17] =]