Home Dashboard Directory Help
Search

Static variable in native method causes exception c0020001 during process exit by Bradley Grainger


Status: 

Closed
 as Won't Fix Help for as Won't Fix


6
0
Sign in
to vote
Type: Bug
ID: 336844
Opened: 4/3/2008 5:37:49 PM
Access Restriction: Public
0
Workaround(s)
view
7
User(s) can reproduce this bug

Description

If:
1) a mixed managed/native C++ assembly is loaded by a .NET application, and
2) that assembly contains a managed C++ method that (during regular program execution) calls a native C++ method, and
3) that native C++ method contains a static variable, and
4) that static variable is of a native type with a destructor,
then the following exception occurs during process exit:

Unhandled exception at 0x75df42eb (kernel32.dll) in App.exe: 0xC0020001: The string binding is invalid.

This occurs because a managed destructor for the static variable has been registered with the atexit function. This registered function is called when DllMain is called with DLL_PROCESS_DETACH, which happens when the C++ assembly is unloaded at exit. However, the CLR has already been shut down, so the attempt to transition back to managed code fails, and exception 0xc0020001 is thrown. The compiler should register a native destructor with atexit, not a managed destructor.
Details
Sign in to post a comment.
Posted by SergeLalonde1 on 2/4/2014 at 7:34 AM
I've also run into this bug in VS2010.
The workaround provided probably works, but involves a lot of rewriting of code in a large application, which is simply not practical especially when the bug is found late in the development cycle just before releasing!
It's also difficult to find where this might occur in a large application since the crash at shutdown will only happen if the local static object was constructed (since the destructor is registered with atexit only if it's been constructed).
So this is a bug that can be lurking anywhere in the code that a customer can encounter at any time, but that our regression tests won't find. Then, try to get the user to explain step-by-step what he did. Might as well ask for the moon.
I hope that this is fixed in VS2012 or VS2013, otherwise, why offer compiler features like C++/CLI that are broken?
Posted by WernerK on 2/9/2011 at 5:20 AM
I had the same problem after removing the source for ManagedWrapper minitialize/mterminate which I had added according to http://support.microsoft.com/kb/814472/EN-US/ years ago with VS 2003 because of linker errors.
I had removed this old source because of Build output messages
"
1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\_vcclrit.h(33): warning CRT1001: _vcclrit.h is deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\_vcclrit.h(124): warning C4996: '__lock_handle': These manual initialisation functions (plus link /noentry) are no longer appropriate for managed code DLLs. Instead, use a normal DLL entrypoint. See online help for more information.
1>         C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\_vcclrit.h(93): Siehe Deklaration von '__lock_handle'
"
Without ManagedWrapper I get errors when the app starts and ends; when I include/activate ManagedWrapper again then the problems disappear.
Maybe usage of ManagedWrapper as described in http://support.microsoft.com/kb/814472/EN-US/ (and adapted from old Managed Extensions (/clr:OldSyntax) to new /clr mode) is another useful workaround for this problem.
Posted by David Furtney on 8/11/2008 at 12:53 PM
We ran into this as well. The only difference is that NativeMethod with the static variable was compiled as managed. I don't think there is any doubt this is a compiler bug. We worked around the issue by moving the static variable to file scope.
Posted by Microsoft on 4/21/2008 at 2:56 PM
The Visual C++ team has triaged the issue you reported with the following message:

The suggested way to work-around this is to use to compilation units, and not rely on #pragma unmanaged/managed (which is pretty fragile).

Here's a workaround:

---------
t.cpp
---------
int NativeMethod(int i);


public ref class Managed
{
public:
        int CallNative(int n)
        {
                return NativeMethod(n);
        }
};

------------
n.cpp
-----------
class Native
{
public:
        Native() { }
        ~Native() { }
};

int NativeMethod(int i)
{
        static Native n;
        return i * 2;
}

cl /MDd /Zi /clr /c t.cpp
cl /EHa /MDd /Zi /c n.cpp
link /dll t.obj n.obj /debug


For further information, you may want to consult one of these resources:
1. Visual C++ triage guidelines:
        http://blogs.msdn.com/vcblog/articles/621116.aspx
2. MSDN forums:
        http://forums.microsoft.com/msdn/default.aspx

Thank you for taking time to send us feedback,
The Visual C++ Team
Posted by Microsoft on 4/4/2008 at 3:03 AM
Thanks for your feedback. We are escalating this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue.

Thank you,
Visual Studio Product Team
Sign in to post a workaround.