Open GoogleCodeExporter opened 9 years ago
It is possible to have a global static RcfInitDeinit instance (that's what RCF
does by default).
You can write code like this:
// Global variable.
RCF::RcfInitDeinit * gpRcfInit;
// This may get called before main().
void somefunc()
{
if (!gpRcfInit)
{
gpRcfInit = new RCF::RcfInitDeinit();
}
// Create a RcfClient instance.
// ...
}
, and then when you shutdown,
delete gpRcfInit;
That way you still have some control over when the initialization and
deinitialization takes place. If you use a global static RcfInitDeinit
variable, you can run into problems with order of init/deinit, especially if
you have other application code running before or after main().
I'd be interested in seeing a stack trace of the assert in boost...
Original comment by jarl.lin...@gmail.com
on 31 Dec 2010 at 2:22
Here is my RCF_SERVER class, which is inherited from RCF::RcfServer
RCF_SERVER::RCF_SERVER(const std::string &pipeName,
const std::string &serverCert /* = "" */,
const std::string &serverCertPass /* = "" */,
const std::string &caCert /* = "" */ )
: RCF::RcfServer(RCF::Win32NamedPipeEndpoint(util::toTstring(pipeName)))
{
}
When I try to declare instance of RCF_SERVER globally I get the assert
mentioned above. When I create RCF_SERVER within main() function I don't get
the assert.
Here is the stack trace of the assert:
//////////////////////////////////////////////////////////////////////////////
Exception:
Unhandled exception at 0x008282c6 in RCF_SERVER.exe: 0xC0000005: Access violation reading location 0x00000004.
Call Stack:
RCF_SERVER.exe!RCF::RcfBoostThreads::boost::mutex::do_lock() Line 52 + 0x3 bytes C++
RCF_SERVER.exe!RCF::RcfBoostThreads::boost::detail::thread::lock_ops<RCF::RcfBoostThreads::boost::mutex>::lock(RCF::RcfBoostThreads::boost::mutex & m={...}) Line 51 C++
RCF_SERVER.exe!RCF::RcfBoostThreads::boost::detail::thread::scoped_lock<RCF::RcfBoostThreads::boost::mutex>::lock() Line 93 + 0xb bytes C++
RCF_SERVER.exe!RCF::RcfBoostThreads::boost::detail::thread::scoped_lock<RCF::RcfBoostThreads::boost::mutex>::scoped_lock<RCF::RcfBoostThreads::boost::mutex>(RCF::RcfBoostThreads::boost::mutex & mx={...}, bool initially_locked=true) Line 84 C++
RCF_SERVER.exe!Platform::Threads::detail::scoped_read_lock::lock() Line 174 C++
RCF_SERVER.exe!Platform::Threads::detail::scoped_read_lock::scoped_read_lock(Platform::Threads::read_write_mutex & rwm={...}) Line 161 C++
RCF_SERVER.exe!util::LogManager::isEnabled(int name=1, int level=2) Line 139 + 0xc bytes C++
RCF_SERVER.exe!RCF::RcfServer::addService(boost::shared_ptr<RCF::I_Service> servicePtr={...}) Line 121 + 0x10 bytes C++
RCF_SERVER.exe!RCF::RcfServer::addServerTransport(boost::shared_ptr<RCF::I_ServerTransport> serverTransportPtr={...}) Line 269 + 0x26 bytes C++
RCF_SERVER.exe!RCF::RcfServer::addEndpoint(const RCF::I_Endpoint & endpoint={...}) Line 1234 C++
RCF_SERVER.exe!RCF::RcfServer::RcfServer(const RCF::I_Endpoint & endpoint={...}) Line 86 C++
RCF_SERVER.exe!RCF_SERVER::RCF_SERVER(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & pipeName="TestPipe", const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & serverCert="", const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & serverCertPass="", const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & caCert="") Line 467 + 0xbe bytes C++
RCF_SERVER.exe!`dynamic initializer for 'server''() Line 525 + 0xec bytes C++
RCF_SERVER.exe!_initterm(void (void)* * pfbegin=0x00c5e260, void (void)* * pfend=0x00c5ee50) Line 903 C
RCF_SERVER.exe!_cinit(int initFloatingPrecision=1) Line 307 + 0xf bytes C
RCF_SERVER.exe!__tmainCRTStartup() Line 249 + 0x7 bytes C
RCF_SERVER.exe!wmainCRTStartup() Line 182 C
kernel32.dll!RegisterWaitForInputIdle() + 0x49 bytes
///////////////////////////////////////////////////////////////////////////////
And the same way I create RCF_CLIENT, which is inherited from my RcfClient.
Same behavior, creating globally gives the boost assert, and no assert if I
create within main().
Trace for client:
//////////////////////////////////////////////////////////////////////////
Exception:
Unhandled exception at 0x007d759b in RCF_CLIENT.exe: 0xC0000005: Access violation reading location 0x0000001c.
Call Stack:
RCF_CLIENT.exe!RCF::RcfBoostThreads::boost::get_slots(bool alloc=false) Line 107 + 0x7 bytes C++
RCF_CLIENT.exe!RCF::RcfBoostThreads::boost::detail::tss::get() Line 163 + 0x7 bytes C++
RCF_CLIENT.exe!RCF::RcfBoostThreads::boost::thread_specific_ptr<RCF::ThreadLocalData>::get() Line 94 + 0x2b bytes C++
RCF_CLIENT.exe!RCF::getThreadLocalData() Line 59 + 0xb bytes C++
RCF_CLIENT.exe!RCF::pushCurrentClientStub(RCF::ClientStub * pClientStub=0x003c37c8) Line 99 + 0x5 bytes C++
RCF_CLIENT.exe!RCF::CurrentClientStubSentry::CurrentClientStubSentry(RCF::ClientStub & clientStub={...}) Line 567 + 0x9 bytes C++
RCF_CLIENT.exe!RCF::AllocateClientParameters<unsigned long,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void>::operator()(RCF::ClientStub & clientStub={...}, const RCF::Void & a1={...}, const RCF::Void & a2={...}, const RCF::Void & a3={...}, const RCF::Void & a4={...}, const RCF::Void & a5={...}, const RCF::Void & a6={...}, const RCF::Void & a7={...}, const RCF::Void & a8={...}, const RCF::Void & a9={...}, const RCF::Void & a10={...}, const RCF::Void & a11={...}, const RCF::Void & a12={...}, const RCF::Void & a13={...}, const RCF::Void & a14={...}, const RCF::Void & a15={...}) Line 1517 + 0xc bytes C++
RCF_CLIENT.exe!RcfClient<I_hCmd>::connect(const RCF::CallOptions & callOptions={...}) Line 143 + 0x228 bytes C++
RCF_CLIENT.exe!RcfClient<I_hCmd>::connect() Line 143 + 0x83 bytes C++
RCF_CLIENT.exe!RCF_CLIENT::RCF_CLIENT(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & connectString="TestPipe", const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & clientCert="", const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & clientCertPass="", const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & caCert="") Line 246 + 0xf bytes C++
RCF_CLIENT.exe!`dynamic initializer for 'client''() Line 264 + 0xee bytes C++
RCF_CLIENT.exe!_initterm(void (void)* * pfbegin=0x00c11260, void (void)* * pfend=0x00c11e50) Line 903 C
RCF_CLIENT.exe!_cinit(int initFloatingPrecision=1) Line 307 + 0xf bytes C
RCF_CLIENT.exe!__tmainCRTStartup() Line 249 + 0x7 bytes C
RCF_CLIENT.exe!wmainCRTStartup() Line 182 C
kernel32.dll!RegisterWaitForInputIdle() + 0x49 bytes
///////////////////////////////////////////////////////////////////////
You may try declaring RCF::RcfInitDeinit() globally to get the boost assert.
Thanks.
Original comment by zoltan.b...@gmail.com
on 7 Jan 2011 at 6:00
The problem with global static objects is that there is no guarantee in which
order they will be contstructed. If you have 2 source files, A.cpp and B.cpp in
your application, and each defines a global static object, then you can't know
which object will be created first.
If you are using RCF in code that is executed before or after main(), you need
to explicitly initialize and deinitialize RCF yourself, by calling RCF::init()
and RCF::deinit().
You can call RCF::init() multiple times, and only the first call will have an
effect. However, you need to call RCF::deinit() as many times as you have
called RCF::init().
Typcially you would call RCF::init() and RCF::deinit() in the ctor and dtor of
the objects that are created before main() is executed.
If you want to determine at which point RCF is being initialized, you can put a
breakpoint in RCF::init() (InitDeinit.cpp).
Original comment by jarl.lin...@gmail.com
on 8 Jan 2011 at 11:35
Original issue reported on code.google.com by
zoltan.b...@gmail.com
on 23 Dec 2010 at 5:58