On Aug 27, 2004, at 3:27 AM, Tom Quarendon wrote:
Right. So to make log4cxx work properly across multiple DLLs with all my C++
classes having static LoggerPtr objects I need to indulge in some serious
use of the GCC "init_priority" attribute to control initialisation order.
Surely there is a recognised way of going this -- doesn't everyone have
static LoggerPtr objects in their classes? All my classes are like :
fred.hpp ======== class Fred { static log4cxx::LoggerPtr logger; ...
};
fred.cpp ========
log4cxx::LoggerPtr Fred::logger = log4cxx::Logger::getLogger("fred");
From what you are saying, in order for this to work properly I need to make
sure that the static initialisation of logger in fred.cpp is done after any
static initialisation in the log4cxx DLL. Maybe the way to do it is
...
Is there a recommended way of doing this kind of stuff?
Looks like we have the dreaded non-local static variable somewhere in log4cxx. The scenario is Item 47 in Effective C++. Any access to static variables within log4cxx needs to be down using local static variables so that initialization is forced to occur on first use. I haven't done a search and the following is a simplistic example. Unsafe:
LogManager gLogManager;
public LoggerPtr Logger::GetLogger(const char* name) {
// gLogManager might not be initialized
return gLogManager.GetLogger(name);
}Safe:
public LogManager& GetGlobalManager() {
// initialization occurs first time through
static LogManager gLogManager;
return gLogManager;
}public LoggerPtr Logger::GetLogger(const char* name) {return GetGlobalManager.GetLogger(name); }
Until it is fixed in log4cxx, you could use the same trick in your code to force the call to getLogger to occur after all static initialization.
class MyClass {private static LoggerPtr GetLogger() {
static LoggerPtr myLogger = log4cxx::Logger::GetLogger("foo");
return myLogger;
}
public MyClass() { LOG4CXX_DEBUG(GetLogger(), "Constructor"); } };
