473,473 Members | 1,843 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

atexit problems on statics inside mixed assembly after moving to VS2005

Aek
We recently moved our large codebase over from VS7 to 8 and found that
we now get access violations in atexit calls at shutdown when
debugging the application in VS2005.
This occurs in static members / singletons (especially meyer type
singletons) which use locally declared static variables. These
variables are normally cleaned up automatically at shutdown of the
application by registering with the atexit. I break point the
destructor on a problem singleton class and notice that the destructor
of this static is called automatically *twice* with atexit. The second
call will cause the crash.

first automatic destruction (call stack):
ExecutableD.exe!GE::CShadowObjects::~CShadowObject s() Line 31 C++
ExecutableD.exe!`GE::CShadowObjects::GetInstance': :`2'::`dynamic
atexit destructor for 'g_ShadowObjects''() + 0xd bytes C++

second automatic destruction (call stack):
ExecutableD.exe!GE::CShadowObjects::~CShadowObject s() Line 31 C++
ExecutableD.exe!`GE::CShadowObjects::GetInstance': :`2'::`dynamic
atexit destructor for 'g_ShadowObjects''() + 0xd bytes C++

We notice that this singleton is implemented using a meyers singleton
that has a local static in the GetInstance() method and no specific
destroy call is needed. When I change the singleton to one that
contains a pointer to class and then call new in the GetInstance, then
it is fine. However I dont want to change tonnes of seemingly valid
code just to work around this crash.

We have no visible problems when we are running the application
outside of the IDE.

I believe it is a similar problem to this one described here:
http://groups.google.com.au/group/mi...5&rnum=3&hl=en

I think that perhaps it has something to do with the mix managed /
unmanaged code or perhaps it has something to do with using /
clr:oldSyntax and Managed Extensions for C++.

This page ( http://msdn2.microsoft.com/en-us/lib...68(VS.80).aspx
) suggests that the /clr option will provide support for "static
initialization of C++ variables in mixed images". Is this also true
then for /clr:oldSyntax ?

We have a number of native C++ libs (no clr) that are then linked into
an executable project built with /clr:oldSyntax. The executable
project contains Managed Extension C++ (hence the need for the
oldSyntax flag)
Ideally we will eventually get rid of Managed Extensions for C++ and
port to C++/CLI.
My main question is:
Could use of oldSyntax and Managed Extensions be a cause of the atexit
problems with static variables in a mixed assembly?

Any other suggestions?

Thankyou for your time
Josh

Jun 21 '07 #1
20 5969
Aek wrote:
My main question is:
Could use of oldSyntax and Managed Extensions be a cause of the atexit
problems with static variables in a mixed assembly?
It could be. Shouldn't be, but it's definitely the case that /clr was
tested a lot more carefully than /clr:oldSyntax for VS2005.
>
Any other suggestions?
Contact PSS. It sounds like you're looking at something complex and subtle
that may require inside knowledge to fully diagnose and understand.

-cd
Jun 21 '07 #2

"Aek" <ae*********@gmail.comwrote in message
news:11**********************@x35g2000prf.googlegr oups.com...
We recently moved our large codebase over from VS7 to 8 and found that
we now get access violations in atexit calls at shutdown when
debugging the application in VS2005.
This occurs in static members / singletons (especially meyer type
singletons) which use locally declared static variables. These
variables are normally cleaned up automatically at shutdown of the
application by registering with the atexit. I break point the
Are you doing the atexit registration in code, or the compiler is doing it
automatically?
destructor on a problem singleton class and notice that the destructor
of this static is called automatically *twice* with atexit. The second
call will cause the crash.

first automatic destruction (call stack):
ExecutableD.exe!GE::CShadowObjects::~CShadowObject s() Line 31 C++
ExecutableD.exe!`GE::CShadowObjects::GetInstance': :`2'::`dynamic
atexit destructor for 'g_ShadowObjects''() + 0xd bytes C++

second automatic destruction (call stack):
ExecutableD.exe!GE::CShadowObjects::~CShadowObject s() Line 31 C++
ExecutableD.exe!`GE::CShadowObjects::GetInstance': :`2'::`dynamic
atexit destructor for 'g_ShadowObjects''() + 0xd bytes C++

We notice that this singleton is implemented using a meyers singleton
that has a local static in the GetInstance() method and no specific
destroy call is needed. When I change the singleton to one that
contains a pointer to class and then call new in the GetInstance, then
it is fine. However I dont want to change tonnes of seemingly valid
code just to work around this crash.

We have no visible problems when we are running the application
outside of the IDE.

I believe it is a similar problem to this one described here:
http://groups.google.com.au/group/mi...5&rnum=3&hl=en

I think that perhaps it has something to do with the mix managed /
unmanaged code or perhaps it has something to do with using /
clr:oldSyntax and Managed Extensions for C++.

This page ( http://msdn2.microsoft.com/en-us/lib...68(VS.80).aspx
) suggests that the /clr option will provide support for "static
initialization of C++ variables in mixed images". Is this also true
then for /clr:oldSyntax ?

We have a number of native C++ libs (no clr) that are then linked into
an executable project built with /clr:oldSyntax. The executable
project contains Managed Extension C++ (hence the need for the
oldSyntax flag)
Ideally we will eventually get rid of Managed Extensions for C++ and
port to C++/CLI.
My main question is:
Could use of oldSyntax and Managed Extensions be a cause of the atexit
problems with static variables in a mixed assembly?

Any other suggestions?

Thankyou for your time
Josh

Jun 21 '07 #3
Aek
On Jun 22, 1:27 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
"Aek" <aek.muld...@gmail.comwrote in message

news:11**********************@x35g2000prf.googlegr oups.com...
We recently moved our large codebase over from VS7 to 8 and found that
we now get access violations in atexit calls at shutdown when
debugging the application in VS2005.
The compiler is generating the atexit registration automatically.

Thanks
Josh
Jun 22 '07 #4

"Aek" <ae*********@gmail.comwrote in message
news:11**********************@j4g2000prf.googlegro ups.com...
On Jun 22, 1:27 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
>"Aek" <aek.muld...@gmail.comwrote in message

news:11**********************@x35g2000prf.googleg roups.com...
We recently moved our large codebase over from VS7 to 8 and found that
we now get access violations in atexit calls at shutdown when
debugging the application in VS2005.

The compiler is generating the atexit registration automatically.
Can you place a breakpoint on atexit and see if the cleanup code is
registered twice?

Are there multiple static objects in the same function, of which it would be
possible that only some are fully constructed due to exceptions?
>
Thanks
Josh

Jun 22 '07 #5
Aek
On Jun 22, 1:27 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
"Aek" <aek.muld...@gmail.comwrote in message

news:11**********************@x35g2000prf.googlegr oups.com...
We recently moved our large codebase over from VS7 to 8 and found that
we now get access violations in atexit calls at shutdown when
debugging the application in VS2005.
The atexit registration is automatically generated by the compiler.
After some experimenting yesterday, I found that if I rebuild one of
my problematic native C++ libs with the /clr:oldSyntax flag then the
problems with the statics in that lib are resolved. Problem is though
that one of the native libs is a graphics engine and it goes from real
time to slower than powerpoint with /clr enabled in the lib, so I
would like to leave the native C++ libs without clr.

Thankyou
Josh

Jun 22 '07 #6
Aek
On Jun 22, 10:44 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
"Aek" <aek.muld...@gmail.comwrote in message

news:11**********************@j4g2000prf.googlegro ups.com...
On Jun 22, 1:27 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
"Aek" <aek.muld...@gmail.comwrote in message
>news:11**********************@x35g2000prf.googleg roups.com...
We recently moved our large codebase over from VS7 to 8 and found that
we now get access violations in atexit calls at shutdown when
debugging the application in VS2005.
The compiler is generating the atexit registration automatically.

Can you place a breakpoint on atexit and see if the cleanup code is
registered twice?
Yes I can, I just need to find where it is. Ill give it a go today.
Are there multiple static objects in the same function, of which it would be
possible that only some are fully constructed due to exceptions?
No, generally the problem is seen in functions that only have a single
static in the function. There seems to be the same problem with all
locally declared statics in native C++ libs (not just 1 case), so I do
not believe exceptions are occuring causing only some statics to be
fully constructed.

Thanks for your help so far.
Josh

Jun 22 '07 #7

"Aek" <ae*********@gmail.comwrote in message
news:11**********************@e9g2000prf.googlegro ups.com...
On Jun 22, 10:44 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
>"Aek" <aek.muld...@gmail.comwrote in message

news:11**********************@j4g2000prf.googlegr oups.com...
On Jun 22, 1:27 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
"Aek" <aek.muld...@gmail.comwrote in message
>>news:11**********************@x35g2000prf.google groups.com...
We recently moved our large codebase over from VS7 to 8 and found
that
we now get access violations in atexit calls at shutdown when
debugging the application in VS2005.
The compiler is generating the atexit registration automatically.

Can you place a breakpoint on atexit and see if the cleanup code is
registered twice?

Yes I can, I just need to find where it is. Ill give it a go today.
>Are there multiple static objects in the same function, of which it would
be
possible that only some are fully constructed due to exceptions?

No, generally the problem is seen in functions that only have a single
static in the function. There seems to be the same problem with all
locally declared statics in native C++ libs (not just 1 case), so I do
not believe exceptions are occuring causing only some statics to be
fully constructed.
Ok, that was the only reason I could think of for having more than one
cleanup handler executed for the same function.

Oh... is there any possibility that the singleton is accessed from other
atexit handlers/static destructors?
>
Thanks for your help so far.
Josh
Jun 22 '07 #8

"Aek" <ae*********@gmail.comwrote in message
news:11*********************@i38g2000prf.googlegro ups.com...
On Jun 22, 1:27 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
>"Aek" <aek.muld...@gmail.comwrote in message

news:11**********************@x35g2000prf.googleg roups.com...
We recently moved our large codebase over from VS7 to 8 and found that
we now get access violations in atexit calls at shutdown when
debugging the application in VS2005.

The atexit registration is automatically generated by the compiler.
After some experimenting yesterday, I found that if I rebuild one of
my problematic native C++ libs with the /clr:oldSyntax flag then the
problems with the statics in that lib are resolved. Problem is though
that one of the native libs is a graphics engine and it goes from real
time to slower than powerpoint with /clr enabled in the lib, so I
would like to leave the native C++ libs without clr.
Can you open your assembly with .NET Reflector and make sure that the
SuppressUnmanagedCodeSecurityAttribute is applied?
>
Thankyou
Josh
Jun 22 '07 #9
Aek
On Jun 22, 10:44 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
Can you place a breakpoint on atexit and see if the cleanup code is
registered twice?
I stepped through the local static creation and can confirm that the
atexit code for the local static is _not_ being called twice, but the
destructor is called twice on the same object.

-Josh

Jun 25 '07 #10
Aek
On Jun 25, 12:32 pm, Aek <aek.muld...@gmail.comwrote:
On Jun 22, 10:44 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
Can you place a breakpoint on atexit and see if the cleanup code is
registered twice?

I stepped through the local static creation and can confirm that the
atexit code for the local static is _not_ being called twice, but the
destructor is called twice on the same object.

-Josh
Sorry I should clarify.
The atexit registration code ( __cdecl atexit ( _PVFV func ) is not
being called more than once on each local static,
but the atexit destruction is called twice on the same static objects
that have previously registered using __cdecl atexit ( _PVFV func )

thanks
Josh

Jun 25 '07 #11
Aek
On Jun 22, 11:48 pm, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
"Aek" <aek.muld...@gmail.comwrote in message

news:11*********************@i38g2000prf.googlegro ups.com...
I found something interesting today that I overlooked before.
The call stack of the atexit calls is showing _cexit calls coming from
different assemblies.
Sorry if this callstack cut and paste comes out a garbled mess in your
reader.. it basically shows that
ConsoleServer_d.dll is calling msvcr80d.dll!_cexit(), which cleans up
the local static... then
ExecuteD.exe calls msvcr80d.dll!_cexit() which again tries to clean up
the local static.

Interesting. ExecuteD.exe is what is run and consoleserver_d.dll is a
dll that it uses. At least now I have somewhere to focus my attention.

Feel free to drop in any thoughts you have about this now, with this
new information.
> ExecuteD.exe!OSMonitor::~OSMonitor() Line 35 C++
ExecuteD.exe!`OSMonitor::GetInstance'::`2'::`dynam ic atexit
destructor for 'instance''() + 0xd bytes C++
msvcr80d.dll!doexit(int code=0, int quick=0, int retcaller=1) Line
553 C
msvcr80d.dll!_cexit() Line 413 + 0xb bytes C
[External Code]
ConsoleServer_d.dll!
<CrtImplementationDetails>::LanguageSupport::_Unin itializeDefaultDomain(void*
cookie = <undefined value>) Line 713 C++
ConsoleServer_d.dll!
<CrtImplementationDetails>::LanguageSupport::Unini tializeDefaultDomain()
Line 729 + 0x8 bytes C++
ConsoleServer_d.dll!
<CrtImplementationDetails>::LanguageSupport::Domai nUnload(System::Object^
source = 0x048ef89c, System::EventArgs^ arguments = <undefined value>)
Line 762 C++
msvcm80d.dll!
<CrtImplementationDetails>::ModuleUninitializer::S ingletonDomainUnload(System::Object^
source = 0x048ef8bc, System::EventArgs^ arguments = <undefined value>)
Line 303 + 0x57 bytes C++
[Frames below may be incorrect and/or missing, no symbols loaded for
mscorwks.dll]
ntdll.dll!7c90e57c()
kernel32.dll!7c80a027()
kernel32.dll!7c80b683()

> ExecuteD.exe!OSMonitor::~OSMonitor() Line 35 C++
ExecuteD.exe!`OSMonitor::GetInstance'::`2'::`dynam ic atexit
destructor for 'instance''() + 0xd bytes C++
msvcr80d.dll!doexit(int code=0, int quick=0, int retcaller=1) Line
553 C
msvcr80d.dll!_cexit() Line 413 + 0xb bytes C
[External Code]
ExecuteD.exe!
<CrtImplementationDetails>::LanguageSupport::_Unin itializeDefaultDomain(void*
cookie = <undefined value>) Line 713 C++
ExecuteD.exe!
<CrtImplementationDetails>::LanguageSupport::Unini tializeDefaultDomain()
Line 729 + 0x8 bytes C++
ExecuteD.exe!
<CrtImplementationDetails>::LanguageSupport::Domai nUnload(System::Object^
source = 0x048ef89c, System::EventArgs^ arguments = <undefined value>)
Line 762 C++
msvcm80d.dll!
<CrtImplementationDetails>::ModuleUninitializer::S ingletonDomainUnload(System::Object^
source = 0x048ef8bc, System::EventArgs^ arguments = <undefined value>)
Line 303 + 0x57 bytes C++
[Frames below may be incorrect and/or missing, no symbols loaded for
mscorwks.dll]
ntdll.dll!7c90e57c()
kernel32.dll!7c80a027()
kernel32.dll!7c80b683()

Regards,
Josh

Jun 25 '07 #12
Aek
On Jun 22, 11:48 pm, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
Can you open your assembly with .NET Reflector and make sure that the
SuppressUnmanagedCodeSecurityAttribute is applied?
The SuppressUnmanagedCodeSecurityAttribute was not applied to the dll
(ConsoleServerD.dll) or the executable (ExecuteD.exe)
I have applied it now and will investigate the results.

Thanks
Josh
Jun 25 '07 #13

"Aek" <ae*********@gmail.comwrote in message
news:11**********************@a26g2000pre.googlegr oups.com...
On Jun 22, 11:48 pm, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
>"Aek" <aek.muld...@gmail.comwrote in message

news:11*********************@i38g2000prf.googlegr oups.com...

I found something interesting today that I overlooked before.
The call stack of the atexit calls is showing _cexit calls coming from
different assemblies.
Sorry if this callstack cut and paste comes out a garbled mess in your
reader.. it basically shows that
ConsoleServer_d.dll is calling msvcr80d.dll!_cexit(), which cleans up
the local static... then
ExecuteD.exe calls msvcr80d.dll!_cexit() which again tries to clean up
the local static.
This seems very important.

I think I'm actually running into a related problem.... the "attempted to
initialize CRT more than once" runtime error. I was looking through the
source code where that error message was generated, and found comments
talking about process-wide state which looked very module-local to me (there
was no __declspec dllimport). Let me see if I can find the particular spot
again.
>
Interesting. ExecuteD.exe is what is run and consoleserver_d.dll is a
dll that it uses. At least now I have somewhere to focus my attention.

Feel free to drop in any thoughts you have about this now, with this
new information.
>ExecuteD.exe!OSMonitor::~OSMonitor() Line 35 C++
ExecuteD.exe!`OSMonitor::GetInstance'::`2'::`dynam ic atexit
destructor for 'instance''() + 0xd bytes C++
msvcr80d.dll!doexit(int code=0, int quick=0, int retcaller=1) Line
553 C
msvcr80d.dll!_cexit() Line 413 + 0xb bytes C
[External Code]
ConsoleServer_d.dll!
<CrtImplementationDetails>::LanguageSupport::_Unin itializeDefaultDomain(void*
cookie = <undefined value>) Line 713 C++
ConsoleServer_d.dll!
<CrtImplementationDetails>::LanguageSupport::Unini tializeDefaultDomain()
Line 729 + 0x8 bytes C++
ConsoleServer_d.dll!
<CrtImplementationDetails>::LanguageSupport::Domai nUnload(System::Object^
source = 0x048ef89c, System::EventArgs^ arguments = <undefined value>)
Line 762 C++
msvcm80d.dll!
<CrtImplementationDetails>::ModuleUninitializer::S ingletonDomainUnload(System::Object^
source = 0x048ef8bc, System::EventArgs^ arguments = <undefined value>)
Line 303 + 0x57 bytes C++
[Frames below may be incorrect and/or missing, no symbols loaded for
mscorwks.dll]
ntdll.dll!7c90e57c()
kernel32.dll!7c80a027()
kernel32.dll!7c80b683()

>ExecuteD.exe!OSMonitor::~OSMonitor() Line 35 C++
ExecuteD.exe!`OSMonitor::GetInstance'::`2'::`dynam ic atexit
destructor for 'instance''() + 0xd bytes C++
msvcr80d.dll!doexit(int code=0, int quick=0, int retcaller=1) Line
553 C
msvcr80d.dll!_cexit() Line 413 + 0xb bytes C
[External Code]
ExecuteD.exe!
<CrtImplementationDetails>::LanguageSupport::_Unin itializeDefaultDomain(void*
cookie = <undefined value>) Line 713 C++
ExecuteD.exe!
<CrtImplementationDetails>::LanguageSupport::Unini tializeDefaultDomain()
Line 729 + 0x8 bytes C++
ExecuteD.exe!
<CrtImplementationDetails>::LanguageSupport::Domai nUnload(System::Object^
source = 0x048ef89c, System::EventArgs^ arguments = <undefined value>)
Line 762 C++
msvcm80d.dll!
<CrtImplementationDetails>::ModuleUninitializer::S ingletonDomainUnload(System::Object^
source = 0x048ef8bc, System::EventArgs^ arguments = <undefined value>)
Line 303 + 0x57 bytes C++
[Frames below may be incorrect and/or missing, no symbols loaded for
mscorwks.dll]
ntdll.dll!7c90e57c()
kernel32.dll!7c80a027()
kernel32.dll!7c80b683()

Regards,
Josh
Jun 26 '07 #14

"Aek" <ae*********@gmail.comwrote in message
news:11**********************@a26g2000pre.googlegr oups.com...
On Jun 22, 11:48 pm, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
>"Aek" <aek.muld...@gmail.comwrote in message

news:11*********************@i38g2000prf.googlegr oups.com...

I found something interesting today that I overlooked before.
The call stack of the atexit calls is showing _cexit calls coming from
different assemblies.
Sorry if this callstack cut and paste comes out a garbled mess in your
reader.. it basically shows that
ConsoleServer_d.dll is calling msvcr80d.dll!_cexit(), which cleans up
the local static... then
ExecuteD.exe calls msvcr80d.dll!_cexit() which again tries to clean up
the local static.

Interesting. ExecuteD.exe is what is run and consoleserver_d.dll is a
dll that it uses. At least now I have somewhere to focus my attention.
You are linking both with /MDd, right?

Jun 26 '07 #15
Aek
On Jun 26, 8:36 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
You are linking both with /MDd, right?
Yeah they are both /MDd

Josh

Jun 26 '07 #16
Aek
On Jun 26, 10:55 am, Aek <aek.muld...@gmail.comwrote:
On Jun 26, 8:36 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
You are linking both with /MDd, right?

Yeah they are both /MDd

Josh
We came to a resolution on this issue. We found that once the
offending C++ DLL that used managed extensions was removed from the
main application, then the problem went away.
Luckily the managed dll didnt do that much, and was mostly prototype
code for a legacy task, so removing it was the best option. We have
other managed dlls that we continue to use, but there was something
specific about how this one was built or used that caused the problem.

We still have not found the root cause of the issue. There is likely
someway that we are building/configuring or using this managed C++ dll
that is causing it to automatically cleanup native types registered
with atexit in a different assembly.

Why the dll calls the CRT cleanup code and the fact that the main
executable does it again is odd, considering that there are a number
of checks in place around that automatic cleanup code to avoid this
problem.

I will spend a few hours today trying to create a small reproducible
case and if the root cause is not clear, perhaps I can post it here
for examination.

Thanks for all your help.
Regards,
Josh Stewart

Jun 27 '07 #17
Aek
On Jun 27, 1:14 pm, Aek <aek.muld...@gmail.comwrote:
On Jun 26, 10:55 am, Aek <aek.muld...@gmail.comwrote:
On Jun 26, 8:36 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
You are linking both with /MDd, right?
Yeah they are both /MDd
Josh

We came to a resolution on this issue. We found that once the
offending C++ DLL that used managed extensions was removed from the
main application, then the problem went away.
Luckily the managed dll didnt do that much, and was mostly prototype
code for a legacy task, so removing it was the best option. We have
other managed dlls that we continue to use, but there was something
specific about how this one was built or used that caused the problem.

We still have not found the root cause of the issue. There is likely
someway that we are building/configuring or using this managed C++ dll
that is causing it to automatically cleanup native types registered
with atexit in a different assembly.

Why the dll calls the CRT cleanup code and the fact that the main
executable does it again is odd, considering that there are a number
of checks in place around that automatic cleanup code to avoid this
problem.

I will spend a few hours today trying to create a small reproducible
case and if the root cause is not clear, perhaps I can post it here
for examination.

Thanks for all your help.
Regards,
Josh Stewart
For anyone that is interested in have a look at a small example of the
problem.. I have created a small reproducible example.
The offending DLL has had all of its managed code removed, so I do not
think it is the managed extensions C++ that was causing the problems
with that DLL.
The issue seems to be related to mixing a /clr built executable + dll
with a native C++ (no clr) library.

You can breakpoint in the destructor of the meyer singleton in the
native C++ lib to see it destroy twice.

Here is the example solution:
http://aek.bur.st/work/Example_AtExit_Issue.zip

If anyone has an idea about what the issue here is, please let me
know :)
Cheers,
Josh Stewart

Jun 28 '07 #18
Aek
On Jun 28, 8:20 pm, Aek <aek.muld...@gmail.comwrote:
On Jun 27, 1:14 pm, Aek <aek.muld...@gmail.comwrote:
On Jun 26, 10:55 am, Aek <aek.muld...@gmail.comwrote:
On Jun 26, 8:36 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
You are linking both with /MDd, right?
Yeah they are both /MDd
Josh
We came to a resolution on this issue. We found that once the
offending C++ DLL that used managed extensions was removed from the
main application, then the problem went away.
Luckily the managed dll didnt do that much, and was mostly prototype
code for a legacy task, so removing it was the best option. We have
other managed dlls that we continue to use, but there was something
specific about how this one was built or used that caused the problem.
We still have not found the root cause of the issue. There is likely
someway that we are building/configuring or using this managed C++ dll
that is causing it to automatically cleanup native types registered
with atexit in a different assembly.
Why the dll calls the CRT cleanup code and the fact that the main
executable does it again is odd, considering that there are a number
of checks in place around that automatic cleanup code to avoid this
problem.
I will spend a few hours today trying to create a small reproducible
case and if the root cause is not clear, perhaps I can post it here
for examination.
Thanks for all your help.
Regards,
Josh Stewart

For anyone that is interested in have a look at a small example of the
problem.. I have created a small reproducible example.
The offending DLL has had all of its managed code removed, so I do not
think it is the managed extensions C++ that was causing the problems
with that DLL.
The issue seems to be related to mixing a /clr built executable + dll
with a native C++ (no clr) library.

You can breakpoint in the destructor of the meyer singleton in the
native C++ lib to see it destroy twice.

Here is the example solution:http://aek.bur.st/work/Example_AtExit_Issue.zip

If anyone has an idea about what the issue here is, please let me
know :)
Cheers,
Josh Stewart
Someone at work found the solution..

In the managed DLL project, remove /NOENTRY from Linker -Command
Line -Additional Options
Note that this is the same as setting "No Entry Point" to "yes" in
Linker -Advanced.

Seems that the /NOENTRY was left in after converting from 2003 to 2005
project and should not be used in this case.

Still not sure why this affects the local statics in the native
library though.

Cheers,
Josh

Jul 2 '07 #19

"Aek" <ae*********@gmail.comwrote in message
news:11**********************@z28g2000prd.googlegr oups.com...
On Jun 28, 8:20 pm, Aek <aek.muld...@gmail.comwrote:
>On Jun 27, 1:14 pm, Aek <aek.muld...@gmail.comwrote:
On Jun 26, 10:55 am, Aek <aek.muld...@gmail.comwrote:
On Jun 26, 8:36 am, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
You are linking both with /MDd, right?
Yeah they are both /MDd
Josh
We came to a resolution on this issue. We found that once the
offending C++ DLL that used managed extensions was removed from the
main application, then the problem went away.
Luckily the managed dll didnt do that much, and was mostly prototype
code for a legacy task, so removing it was the best option. We have
other managed dlls that we continue to use, but there was something
specific about how this one was built or used that caused the problem.
We still have not found the root cause of the issue. There is likely
someway that we are building/configuring or using this managed C++ dll
that is causing it to automatically cleanup native types registered
with atexit in a different assembly.
Why the dll calls the CRT cleanup code and the fact that the main
executable does it again is odd, considering that there are a number
of checks in place around that automatic cleanup code to avoid this
problem.
I will spend a few hours today trying to create a small reproducible
case and if the root cause is not clear, perhaps I can post it here
for examination.
Thanks for all your help.
Regards,
Josh Stewart

For anyone that is interested in have a look at a small example of the
problem.. I have created a small reproducible example.
The offending DLL has had all of its managed code removed, so I do not
think it is the managed extensions C++ that was causing the problems
with that DLL.
The issue seems to be related to mixing a /clr built executable + dll
with a native C++ (no clr) library.

You can breakpoint in the destructor of the meyer singleton in the
native C++ lib to see it destroy twice.

Here is the example
solution:http://aek.bur.st/work/Example_AtExit_Issue.zip

If anyone has an idea about what the issue here is, please let me
know :)
Cheers,
Josh Stewart

Someone at work found the solution..

In the managed DLL project, remove /NOENTRY from Linker -Command
Line -Additional Options
Note that this is the same as setting "No Entry Point" to "yes" in
Linker -Advanced.

Seems that the /NOENTRY was left in after converting from 2003 to 2005
project and should not be used in this case.

Still not sure why this affects the local statics in the native
library though.
The CRT entry-point sets up the various arrays and linked lists that handle
destruction of statics and globals for the module. If it wasn't called,
those lists wouldn't be set up correctly, and apparently the ones from the
main application were used instead. So all the statics were cleaned up,
instead of just the ones for the local module. Or something like that.
>
Cheers,
Josh

Jul 2 '07 #20
Aek
On Jul 2, 9:10 pm, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
The CRT entry-point sets up the various arrays and linked lists that handle
destruction of statics and globals for the module. If it wasn't called,
those lists wouldn't be set up correctly, and apparently the ones from the
main application were used instead. So all the statics were cleaned up,
instead of just the ones for the local module. Or something like that.
Yeah in VS2003 I think we were manually initializing the CRT by
calling the functions in "_vcclrit.h" such as __crt_dll_initialize()
and using the /NOENTRY. But in VS2005 this is not required. I think it
was either a result of a automatic conversion of that project that
wasnt checked, or a conversion that was checked plus a bad merge.
It was hard to spot because the /NOENTRY was sitting in the Linker ->
Command Line -Additional Options (where we rarely have anything
specified)

Cheers,

-Josh

Jul 4 '07 #21

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Paul | last post by:
Given test.exe - C++, non-mfc, non-clr bar.dll - C++, non-mfc, non-cr foo.dll - C++, non-mfc, clr, some managed and some unmanaged If I run tests from a local drive, say c:\bin, I can...
3
by: Lonewolf | last post by:
Hi all, I'm having difficulties passing data back to managed class from my native class when the data is generated from within a native thread in the native class itself. I will give the following...
0
by: DPR | last post by:
Hi, I've recognized that a mixed assembly with unmanaged exports and an unmanaged "DllMain" can't be unloaded from a (unmanaged) process, even if it's no longer needed and the (unmanaged)...
3
by: dfranzen | last post by:
Hi *, I'm in the process of porting an ANSI C++ project from a UNIX platform to .NET. After "getting rid of" some platform-specific stuff I managed to compile the first two libraries into mixed...
2
by: MC-Advantica | last post by:
I have a managed C++ based assembly referencing a bunch of unmanaged DLLs. I strongly name the the mixed assembly, and place it in the GAC. I write a VB client and reference the managed assembly:...
1
by: =?Utf-8?B?SmltIFdhbHNo?= | last post by:
I have an VC++ MFC Win32 application that isn't working correctly when I build it with VS2005. The problem seems to be in some ADO ActiveX controls that came with VS6 and are now out of support....
7
by: =?Utf-8?B?SmltIFdhbHNo?= | last post by:
I'm new to working with mixed assemblies. All of my previous experience has been with VC++/MFC in native, unmanaged applications. When I create a mixed assembly in which one or more of the files...
0
by: =?Utf-8?B?SmltIFdhbHNo?= | last post by:
I have a mixed assembly. Visual C++/MFC and a .NET C# Windows Form User Control to be used in an MFC dialog box. Most of the modules in the Visual C++/MFC part of the project are...
1
by: =?Utf-8?B?SmltIFdhbHNo?= | last post by:
VS2005 - VC++/MFC: most modules compiled as native. Two modules compiled as /clr (managed). One of these two modules uses a .NET C# Windows form User control in an MFC dialog box. The program...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
0
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.