我正在开发一个项目,我们有几个可共享多个目标文件的可执行文件。我们希望为所有可执行文件添加日志记录,并且有一个库可以执行此操作。
但是,转到每个可执行文件的main()
函数并添加相同的样板函数调用以启动日志记录似乎很笨拙。这意味着我们再次写同样的东西,并且在可维护性和DRY(“不要重复自己”)上松了一口气。如果我们能够系统地确保在调用main函数之前启动日志记录会很好。
我发现在libc ++中有一些函数可以调用main,也可以覆盖它们。但是,我不知道它们是什么,并想象如果我们不小心,这可能会破坏它们。有谁知道如何做到这一点?或者,如果这太过分了,还有其他关于如何进行的建议吗?
我们正在使用带有g ++ 4.8的C ++ 11,如果它有所不同。
答案 0 :(得分:5)
您无需通过修改main().
您应该在共享对象库中的全局范围内创建一个类。这个类的构造函数将执行"初始化"你想做什么,在main()运行之前,它的析构函数将在main()之后运行。
您需要处理的问题是,对于任何其他全局范围对象,此初始化和销毁的顺序不能保证是确定性的。所有这些都可以放在一个.cpp
编译单元中。
class LoggingManager // you can make this a singleton but not necessary
{
public:
LoggingManager();
~LoggingManager();
};
LoggingManager::LoggingManager()
{
// your initialisation code goes here
}
LoggingManager::~LoggingManager()
{
// your clean-up code goes here. It should not throw
}
LoggingManager loggingManagerStaticInstance;
请注意,"静态初始化"存在很小的危险。问题,这意味着在首次访问编译单元之前,可能无法加载loggingManagerStaticInstance
。
实际上,如果初始化在第一次需要之前发生(有点像单身),那么它是否在main()
之后并不重要但这意味着你的编译单元可能需要包含某些东西保证会被拉进来。
如果你想"坚持"对于gnu或类似的,它们提供了可能解决它的__attribute__(constructor)
,尽管有一种更简单的方法可以实现一些虚拟extern int实现或虚函数返回一个int,它可以从实际用于实现日志记录的任何头中调用。