making code native in a C++/CLI program

B

Ben Voigt

Under certain circumstances I get:
First-chance exception at 0x7c812a5b (kernel32.dll) in LTMGUI.exe:
0xC0020001: The string binding is invalid.
First-chance exception at 0x7c812a5b (kernel32.dll) in LTMGUI.exe: Microsoft
C++ exception: [rethrow] at memory location 0x00000000..
Unhandled exception at 0x7c812a5b (kernel32.dll) in LTMGUI.exe: 0xC0020001:
The string binding is invalid.

Googling this exception brought me to a blog posting by Chris Brumme
indicating that this is a result of making an unmanaged->managed transition
while the CLR is shutting down
(http://blogs.msdn.com/cbrumme/archive/2003/04/15/51318.aspx)

However, on the line where the debugger stops, I do not believe the compiler
should be generating a call into managed code. I do not want this thread to
make a call to managed code. I do not want this code to crash if the CLR
shuts down. I do not want this code to stop when the CLR does a garbage
collection.

The debugger stops in the following function:

/**
** \brief Performs in-place default construction
** \param[in] length Number of elements to allocate/construct
** \return Pointer to memory containing \c length elements, default
constructed
**/
static T* init( size_t const length )
{
// would like p = new T[length]
// but can't mix and match in-place copy construction
// with array form of new, since one needs to be freed with
// ::blush:perator delete, and the other with T::blush:perator delete[]
T* p = (T*)::blush:perator new(length * sizeof (T));
size_t left = length;

try {
while (left-- > 0)
new (p + left) T(); // 0xC0020001 thrown here
}
catch (...) {
// in case of exception, destroy any elements already created
while (++left < length)
(p + left)->~T();

throw;
}

return p;
}


T is a typename template parameter which is a pointer to native struct. The
template definition is bracketed by pragma managed(push, off). So is the
declaration of the instantiating variable. The first function on the stack
not in the template class is in a .cpp file protected by pragma unmanaged.

Why is the compiler using managed code, and how do I make it stop!?! A
placement new for a pointer type shouldn't do anything anyway.
 
B

Ben Voigt

Ben Voigt said:
Under certain circumstances I get:
First-chance exception at 0x7c812a5b (kernel32.dll) in LTMGUI.exe:
0xC0020001: The string binding is invalid.
First-chance exception at 0x7c812a5b (kernel32.dll) in LTMGUI.exe:
Microsoft C++ exception: [rethrow] at memory location 0x00000000..
Unhandled exception at 0x7c812a5b (kernel32.dll) in LTMGUI.exe:
0xC0020001: The string binding is invalid.

BTW here is the call stack:
kernel32.dll!_RaiseException@16() + 0x52 bytes
mscorwks.dll!COMPlusThrowBoot() + 0x1c bytes
mscorwks.dll!_StubRareDisableTHROWWorker@8() + 0x24 bytes
mscorwks.dll!_StubRareDisableTHROW() + 0x9 bytes
XYZ.dll!lenarray<ABC *>::init(const unsigned int length=1) Line 97 + 0x11
bytes C++
 
J

Jeffrey Tan[MSFT]

Hi Ben,

What's version of .Net are you using? .Net1.1 managed C++ or .Net2.0 CLI?
Based on your post title, I assume you are using VS2005 and .Net2.0, yes?

Based on the exceptions information you provided, there are 3 records:
1. First-chance exception at 0x7c812a5b
2. First-chance exception at 0x7c812a5b (C++ exception: [rethrow] at memory
location 0x00000000)
3. Unhandled exception at 0x7c812a5b

It reveals that 0xC0020001 first chance exception generates in try block,
which is caught by catch block. Then the "throw" statement rethrows the
exception again, which is not caught by any other exception handler, so it
will finally result in an unhandled second chance exception in debugger.

Although T* points to a native structure, the init() method executes in
/clr mode, which means the init() method is the managed function. So the
"throw" statement is implement by the CLR instead of the CRT native code.
However, based on the cbrumme's blog entry, when the exception is rethrown
by the "throw" statement, the CLR has started shutting down. Then the
"throw" statement calls into the CLR for managed exception throwing, which
results in the BOOTUP_EXCEPTION_COMPLUS generated with the stack trace you
got.

I am not sure if this design is what you expected. If you want to execute
the init() method "throw" statement in native mode, you may also use
#pragma managed(push, off) to mark init() method:
http://msdn2.microsoft.com/en-us/library/0adb9zxe(VS.80).aspx

Hope this helps.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
B

Ben Voigt

"Jeffrey Tan[MSFT]" said:
Hi Ben,

What's version of .Net are you using? .Net1.1 managed C++ or .Net2.0 CLI?
Based on your post title, I assume you are using VS2005 and .Net2.0, yes?

Yes, C++/CLI compiler from VS2005 w/SP1 beta. Is the final SP1 released
yet?
Based on the exceptions information you provided, there are 3 records:
1. First-chance exception at 0x7c812a5b
2. First-chance exception at 0x7c812a5b (C++ exception: [rethrow] at
memory
location 0x00000000)
3. Unhandled exception at 0x7c812a5b

It reveals that 0xC0020001 first chance exception generates in try block,
which is caught by catch block. Then the "throw" statement rethrows the
exception again, which is not caught by any other exception handler, so
it
will finally result in an unhandled second chance exception in debugger.

Although T* points to a native structure, the init() method executes in
/clr mode, which means the init() method is the managed function. So the
"throw" statement is implement by the CLR instead of the CRT native code.
Thanks for looking at this problem. The init function is however defined
inline inside a template class, which is inside pragma managed(push, off).
The typename parameter to the class is a "pointer to native struct". The
variable declared using the template, and the call point for the init
function, are also inside pragma managed(push, off).
However, based on the cbrumme's blog entry, when the exception is rethrown
by the "throw" statement, the CLR has started shutting down. Then the
"throw" statement calls into the CLR for managed exception throwing, which
results in the BOOTUP_EXCEPTION_COMPLUS generated with the stack trace you
got.
The BOOTUP_EXCEPTION_COMPLUS is not being generated by my throw statement,
the throw statement rethrows BOOTUP_EXCEPTION_COMPLUS that occurred inside
the try block.

It is the call to placement new that the compiler has translated as a
managed call which is producing the exception. I'm somewhat surprised that
this call to placement new isn't optimized away during template
instantiation, even in release mode (since the constructor for a pointer
type is a no-op), followed by the loop, and exception frame.

In general I believe these two sequences should be equivalent for any T,
barring stack unwinding:

{
T temp; // reserves memory; calls default constructor
} // destructor called at end of scope

or

BYTE untyped[sizeof (T)]; // reserve memory
new (untyped) T(); // call default constructor
{
T& temp = *(T*)untyped;
}
((T*)untyped)->~T(); // destructor called at end of scope


I am not sure if this design is what you expected. If you want to execute
the init() method "throw" statement in native mode, you may also use
#pragma managed(push, off) to mark init() method:
http://msdn2.microsoft.com/en-us/library/0adb9zxe(VS.80).aspx

Hope this helps.

I have implemented alternate versions of the function and used type traits
to select an empty init function in the case where T is a pointer type.
I've eliminated another source of the BOOTUP_EXCEPTION_COMPLUS by placing
pragma managed(push, off) around the STL headers. Is there any way to
ensure that a particular thread doesn't call into managed code? Can I
inspect TLS to determine if the managed runtime ever initialized on the
thread?
 
J

Jeffrey Tan[MSFT]

Hi Ben,

Thanks for your feedback and confirm.

Yes, based on your further information, it seems that init() method should
also execute the native code, which makes the exception very strange.

Is it possible for you to create a little sample project to demonstrate
this problem? So that I will give a reproduce on my side. This will be
easier for us to understand and debug this problem, thanks.

To identify if one thread is managed or not, you may use windbg to attach
your application and then use SOS.dll "!threads" command to list all the
managed threads. John Robbins' article below shows the steps of using
SOS.dll in windbg:
http://msdn.microsoft.com/msdnmag/issues/03/06/Bugslayer/

I will wait for the reproduce project for debugging. Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
T

Tamas Demjen

C

Carl Daniel [VC++ MVP]

Tamas Demjen said:
Was releasedon on Dec 14, but there is not a single reference to it on
MSDN. They kept it in secret, its not announced or linked anywhere. It's
not on the MSDN Subscribers Download page either. The only way to find it
is performing a google search, which of course returns the download link:

http://www.microsoft.com/downloads/...AB-E2D4-4C96-B39D-37BAF6B5B1DC&displaylang=en

While there isn't much fanfare on the MSDN site, it's not quite as bad as
you describe -

From the MSDN home page, clicking on "Visual Studio" and then "Downloads"
and then "Product Updates" and then "Service Packs" takes you to

http://msdn2.microsoft.com/en-us/vstudio/aa718359.aspx

which has the download link.

-cd
 
T

Tamas Demjen

Carl said:
While there isn't much fanfare on the MSDN site, it's not quite as bad as
you describe -

Thanks Carl. There is, indeed, a link to SP1 on the front page now. When
I was checking it last time around the 21st of December, it was not on
Subscribers Downloads, Announcements, nor the VS 2005 Developer Center
section. If they had a download link, I must have missed it. Right now
it's very visible, which is a good thing.

Tom
 
J

Jeffrey Tan[MSFT]

Hi Tamas,

Thank you for pointing this out. I forget to provide it to Ben.

Additionally, below recently released KB documented the bugs fixed by SP1:
"List of bugs that are fixed in Visual Studio 2005 Service Pack 1"
http://support.microsoft.com/kb/918526

Hope it helps.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
B

Ben Voigt

"Jeffrey Tan[MSFT]" said:
Hi Ben,

Thanks for your feedback and confirm.

Yes, based on your further information, it seems that init() method should
also execute the native code, which makes the exception very strange.

Is it possible for you to create a little sample project to demonstrate
this problem? So that I will give a reproduce on my side. This will be
easier for us to understand and debug this problem, thanks.

Since I've since corrected the registry settings that caused our software to
bail out such that the CLR exited early and caused the exception, I can no
longer get the exception to reproduce. However, generating the undesired
unmanaged->managed code transition is quite straightforward. Simply
instantiating the function I gave you on the type void* generates managed
constructor calls.

The compiler generates a managed function call for "new (p + left) T();",
even when T is void* or (struct native)*.

#pragma managed(push, off)
template <typename T>
class lenarray
{
/**
** \brief Performs in-place default construction
** \param[in] length Number of elements to allocate/construct
** \return Pointer to memory containing \c length elements, default
constructed
**/
static T* init( size_t const length )
{
// would like p = new T[length]
// but can't mix and match in-place copy construction
// with array form of new, since one needs to be freed with
// ::blush:perator delete, and the other with T::blush:perator delete[]
T* p = (T*)::blush:perator new(length * sizeof (T));
size_t left = length;

try {
while (left-- > 0)
new (p + left) T(); // 0xC0020001 thrown here
}
catch (...) {
// in case of exception, destroy any elements already created
while (++left < length)
(p + left)->~T();

throw;
}

return p;
}

size_t m_Length;
T* m_pElements;
public:
lenarray(size_t length) : m_Length(length), m_pElements(init(length)) {}
// copy constructor, destructor, accessors, operator[] all not needed for
reproducing problem
};

lenarray<void*>test(10);

#pragma managed(off)
 
B

Ben Voigt

"Jeffrey Tan[MSFT]" said:
Hi Tamas,

Thank you for pointing this out. I forget to provide it to Ben.

Additionally, below recently released KB documented the bugs fixed by SP1:
"List of bugs that are fixed in Visual Studio 2005 Service Pack 1"
http://support.microsoft.com/kb/918526

Some of those look like they will help various issues I've experienced and
had to work around in the past.

When I ran the SP1 installer, it updated Team Explorer, but never said
anything about Visual Studio Professional.... how can I check that I'm using
the SP1 final compiler?
 
J

Jeffrey Tan[MSFT]

Hi Ben,

You may open "Help"->"About Microsoft Visual Studio" option to check if the
SP1 is applied.

For the VS2005 with SP1 installed, there will be one item in the listbox
with the information below:

"Microsoft Visual Studio 2005 Team Suite - ENU Service Pack 1 (KB926601)

This service pack is for Microsoft Visual Studio 2005 Team Suite - ENU.
If you later install a more recent service pack, this service pack will be
uninstalled automatically.
For more information, visit http://support.microsoft.com/kb/926601"

Hope this helps.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

Jeffrey Tan[MSFT]

Hi Ben,

Happy New Year!

Yes, I have consulted this issue with some other MS devs, below is their
comment:

"Once you give the /clr switch, which code is managed and which is native
is not easily predicted.
"pragma managed" doesn't work 100%.

If you want native code, don't use /clr.

And then you can link it all together no problem."

Hope it helps.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
B

Ben Voigt

"Jeffrey Tan[MSFT]" said:
Hi Ben,

You may open "Help"->"About Microsoft Visual Studio" option to check if
the
SP1 is applied.

For the VS2005 with SP1 installed, there will be one item in the listbox
with the information below:

"Microsoft Visual Studio 2005 Team Suite - ENU Service Pack 1 (KB926601)

I have VS2005 Pro installed along with Team Explorer.... my Help About
contains:

Microsoft Visual Studio 2005
Version 8.0.50727.762 (SP.050727-7600)
Microsoft .NET Framework
Version 2.0.50727

Installed Edition: Professional

Microsoft Visual Basic 2005 77626-009-0000007-41845
Microsoft Visual Basic 2005

Microsoft Visual C# 2005 77626-009-0000007-41845
Microsoft Visual C# 2005

Microsoft Visual C++ 2005 77626-009-0000007-41845
Microsoft Visual C++ 2005

Microsoft Visual J# 2005 77626-009-0000007-41845
Microsoft Visual J# 2005

Microsoft Visual Web Developer 2005 77626-009-0000007-41845
Microsoft Visual Web Developer 2005

Microsoft Web Application Projects 2005 77626-009-0000007-41845
Microsoft Web Application Projects 2005
Version 8.0.50727.363

Visual Studio 2005 Team Explorer 77626-009-0000007-41845
Microsoft Visual Studio 2005 Team Explorer
Version 8.0.50727.762

Microsoft.SpecSharp 1.0.6404.0
Microsoft® Spec# Compiler, Version 1.0.6404.0

Team Foundation PowerToys 1.0
PowerToys that extend the Team Foundation integration with Visual Studio
 
J

Jeffrey Tan[MSFT]

Hi Ben,

Yes, I think the SP1 is actived on your VS2005. After applying the SP1, the
version will upgrade from "Version 8.0.50727.42 (RTM.050727-4200)" to
"Version 8.0.50727.762 (SP.050727-7600)".

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top