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
移动到函数 initialize
或 terminate
中,错误会消失。
或者,如果我在函数 main
中初始化一个普通的 Agent
,我的意思是我不使用 getInstance
,而是这样做:Agent agent;
,错误将消失也是。
或者,如果我在函数 getInstance
中新建一个 Agent
,而不是使用 static
,错误也会消失。
这是我的第一个问题。
我的第二个问题在这里:
请注意Log
的析构函数中有注释:
// do NOT delete osAppender and patternLayout
我发表这样的评论是因为我认为它们都是来自new
的指针,所以我可以而且应该删除它们。但是如果我删除其中一个或两个,我会得到同样的错误:
Signal received:SIGSEGV
.
问题已解决。
我遇到这个问题是因为 log
和 agent
这里都是静态的。
意思是在main
函数中afterreturn 0;
都会free,我们无法决定free的顺序
这样的话,显然在调用agent
的虚函数之前,log
已经空闲了,所以我在虚函数中调用terminate()
的时候,就会报错[=17] =]
我正在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
移动到函数 initialize
或 terminate
中,错误会消失。
或者,如果我在函数 main
中初始化一个普通的 Agent
,我的意思是我不使用 getInstance
,而是这样做:Agent agent;
,错误将消失也是。
或者,如果我在函数 getInstance
中新建一个 Agent
,而不是使用 static
,错误也会消失。
这是我的第一个问题。
我的第二个问题在这里:
请注意Log
的析构函数中有注释:
// do NOT delete osAppender and patternLayout
我发表这样的评论是因为我认为它们都是来自new
的指针,所以我可以而且应该删除它们。但是如果我删除其中一个或两个,我会得到同样的错误:Signal received:SIGSEGV
.
问题已解决。
我遇到这个问题是因为 log
和 agent
这里都是静态的。
意思是在main
函数中afterreturn 0;
都会free,我们无法决定free的顺序
这样的话,显然在调用agent
的虚函数之前,log
已经空闲了,所以我在虚函数中调用terminate()
的时候,就会报错[=17] =]