473,770 Members | 7,287 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

mixed-mode DLL: register corruption occurs when managed C++ callsunmanaged C++

We are using Visual Studio.NET 2003 in our project with .NET framework
1.1. One of our libraries is a mixed-mode dll assembly consisting of
one managed C++ library, and several unmanaged C++ libraries. We are
using managed C++ as a bridge between managed .NET code and unmanaged
C++ code, which I'm sure is a fairly common practice. The managed C++
library is compiled with /CLR whereas all other libraries are compiled
without /CLR because they are strictly native C++ code.

Now let me take you on a journey.

A class like the following is written in unmanaged C++:

////////////////////////////////////////////////////////////////

/// UnmanagedClass. h

class UnmanagedClass
{
public:
virtual bool returnsFalse() const;
};

/// UnmanagedClass. cpp

bool
UnmanagedClass: :returnsFalse() const
{
return false;
}

////////////////////////////////////////////////////////////////

then consider the following managed code:

////////////////////////////////////////////////////////////////

/// ManagedClass.cp p

void
ManagedClass::f oo()
{
UnmanagedClass* obj = new UnmanagedClass( );
bool res = obj->returnsFalse() ;
assert(!res); // <= this assertion fails
}

////////////////////////////////////////////////////////////////

I have been able to consistently reproduce this problem by running an
example very similar to the above *before* executing any of my other
code. At first I could hardly believe what I was seeing -- I actually
watched a function return "false", but the caller got back "true"! Not
good at all. Looking at the machine code, the "returnsFal se" function
is as follows:

07778D90 push ebp
07778D91 mov ebp,esp
07778D93 sub esp,8
07778D96 mov dword ptr [ebp-8],0CCCCCCCCh
07778D9D mov dword ptr [ebp-4],0CCCCCCCCh
07778DA4 mov dword ptr [ebp-4],ecx
07778DA7 xor al,al
07778DA9 mov esp,ebp
07778DAB pop ebp
07778DAC ret 4

////////////////////////////////////////////////////////////////

The boolean result of the function is returned in the "AL" register,
which does equal 0 at the time when the "ret" instruction is executed.
Here are all the register values at the time "ret" is executed:

////////////////////////////////////////////////////////////////

EAX = 07751400 EBX = 0012F594 ECX = 07455B48 EDX = 07455B98
ESI = 001532A8 EDI = 00000000 EIP = 0775147E ESP = 0012F58C
EBP = 0012F5E4 EFL = 00000246

////////////////////////////////////////////////////////////////

The caller looks like this:

00000038 push 170470h
0000003d call F8D18698
00000042 movzx ebx,al <=== control returns here
(expecting result in "AL")
00000045 movzx eax,bl
00000048 mov dword ptr [ebp-0Ch],eax
0000004b nop
0000004c mov ebx,dword ptr [ebp-0Ch]
0000004f jmp 00000051
00000051 mov eax,ebx
00000053 pop ebx
00000054 pop esi
00000055 pop edi
00000056 mov esp,ebp
00000058 pop ebp
00000059 ret

////////////////////////////////////////////////////////////////

When control returns to the caller (at 000000042h), the registers
have changed to the following:

////////////////////////////////////////////////////////////////

EAX = 00000001 EBX = 07751470 ECX = 00000004 EDX = 00000000
ESI = 07455B48 EDI = 07455B98 EBP = 0012F63C ESP = 0012F624

////////////////////////////////////////////////////////////////

As you can see, the "AL" register has been set to "01". Actually the
entire EAX register has been set to "00000001". Since the "ret"
instruction should never modify the contents of the AL register, I had
another look at the point of time when the "ret 4" is executed. The
call stack reveals the likely culprit:

////////////////////////////////////////////////////////////////
libjss.dll!cse: :ResourceRequir ement::equals(

constcse::Resou rceRequirement & rhs={...}) Line 27 C++
mscorwks.dll!79 25c098()
^^^^^^^^^^^^^^^ ^^^^ probable culprit ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^
libjss.dll!utl: :equals<cse::Re sourceRequireme nt>(
cse::ResourceRe quirement* lhs = 0x07455b48,
cse::ResourceRe quirement* rhs = 0x07455b98) Line 134 + 0x15
bytes C++
libjss.dll!jss. ResourceRequire ment.Equals(
System.Object rhs = 0x04ce6ba0)
Line 33 + 0xc bytes C++
demo_cs.exe!dem o_cs.demo_cs.ev ilBug() Line 143 + 0x9 bytes C#
demo_cs.exe!dem o_cs.demo_cs.Ma in(string[] args = {Length=5})
Line 317 C#

////////////////////////////////////////////////////////////////

The register mangling must occur in mscorwks.dll, which I assume is
responsible for managing calls from managed into unmanaged code. I
found that if I compiled the native C++ projects with /CLR switch,
then the problem goes away (because there is no longer a transition
into unmanaged code). However, compiling with "/CLR" has significant
disadvantages, including:

1. can't use pre-compiled headers -- they make a BIG difference
compilation performance
2. debugging of unmanaged code becomes very difficult

I should say that I have followed the instructions for mixed-mode DLLs
that are described in a KB article called "Converting Managed Extensions
for C++ Projects from Pure Intermediate Language to Mixed Mode".

The debugging problem when using "/CLR" _also_ implicates mscorwks.dll.
Basically when I step into unmanaged C++ code, the debugger says "there
is no source code for the current location". Looking at the call stack,
I can see that mscorwks.dll!79 25c098 is on TOP of the call stack, and
the native C++ code that I am trying to debug is next down on the call
stack. The end result is that debugging the native C++ code (that was
compiled with "/CLR") is a very painful exercise.

So I have to choose between:

a) having my code execute as I wrote it ("/CLR" switch turned ON for
native C++)
-OR-
b) being able to debug the code ("/CLR" switch turned OFF for native
C++)

In other words, if I want to be able to debug the code, then I must
accept the fact that the code will not always execute as I wrote it.
Not a good situation to be in! I don't see what I can do now except
try to get help.

Please ... help ....

-Adam McKee // sp**@adam-mckee.net

Nov 16 '05 #1
5 2956
I believe this is a known bug, although when I looked recently I was unable
to find any document on the MSDN web site that seems relevant to this bug.

Another alternative it to return BOOL (a typedef for int) instead of bool.
IIRC, this marshalling bug only affects functions that return bool.

-cd
Adam McKee wrote:
We are using Visual Studio.NET 2003 in our project with .NET framework
1.1. One of our libraries is a mixed-mode dll assembly consisting of
one managed C++ library, and several unmanaged C++ libraries. We are
using managed C++ as a bridge between managed .NET code and unmanaged
C++ code, which I'm sure is a fairly common practice. The managed C++
library is compiled with /CLR whereas all other libraries are compiled
without /CLR because they are strictly native C++ code.

Now let me take you on a journey.

A class like the following is written in unmanaged C++:

////////////////////////////////////////////////////////////////

/// UnmanagedClass. h

class UnmanagedClass
{
public:
virtual bool returnsFalse() const;
};

/// UnmanagedClass. cpp

bool
UnmanagedClass: :returnsFalse() const
{
return false;
}

////////////////////////////////////////////////////////////////

then consider the following managed code:

////////////////////////////////////////////////////////////////

/// ManagedClass.cp p

void
ManagedClass::f oo()
{
UnmanagedClass* obj = new UnmanagedClass( );
bool res = obj->returnsFalse() ;
assert(!res); // <= this assertion fails
}

////////////////////////////////////////////////////////////////

I have been able to consistently reproduce this problem by running an
example very similar to the above *before* executing any of my other
code. At first I could hardly believe what I was seeing -- I actually
watched a function return "false", but the caller got back "true"!
Not good at all. Looking at the machine code, the "returnsFal se"
function
is as follows:

07778D90 push ebp
07778D91 mov ebp,esp
07778D93 sub esp,8
07778D96 mov dword ptr [ebp-8],0CCCCCCCCh
07778D9D mov dword ptr [ebp-4],0CCCCCCCCh
07778DA4 mov dword ptr [ebp-4],ecx
07778DA7 xor al,al
07778DA9 mov esp,ebp
07778DAB pop ebp
07778DAC ret 4

////////////////////////////////////////////////////////////////

The boolean result of the function is returned in the "AL" register,
which does equal 0 at the time when the "ret" instruction is executed.
Here are all the register values at the time "ret" is executed:

////////////////////////////////////////////////////////////////

EAX = 07751400 EBX = 0012F594 ECX = 07455B48 EDX = 07455B98
ESI = 001532A8 EDI = 00000000 EIP = 0775147E ESP = 0012F58C
EBP = 0012F5E4 EFL = 00000246

////////////////////////////////////////////////////////////////

The caller looks like this:

00000038 push 170470h
0000003d call F8D18698
00000042 movzx ebx,al <=== control returns here
(expecting result in "AL")
00000045 movzx eax,bl
00000048 mov dword ptr [ebp-0Ch],eax
0000004b nop
0000004c mov ebx,dword ptr [ebp-0Ch]
0000004f jmp 00000051
00000051 mov eax,ebx
00000053 pop ebx
00000054 pop esi
00000055 pop edi
00000056 mov esp,ebp
00000058 pop ebp
00000059 ret

////////////////////////////////////////////////////////////////

When control returns to the caller (at 000000042h), the registers
have changed to the following:

////////////////////////////////////////////////////////////////

EAX = 00000001 EBX = 07751470 ECX = 00000004 EDX = 00000000
ESI = 07455B48 EDI = 07455B98 EBP = 0012F63C ESP = 0012F624

////////////////////////////////////////////////////////////////

As you can see, the "AL" register has been set to "01". Actually the
entire EAX register has been set to "00000001". Since the "ret"
instruction should never modify the contents of the AL register, I had
another look at the point of time when the "ret 4" is executed. The
call stack reveals the likely culprit:

////////////////////////////////////////////////////////////////
> libjss.dll!cse: :ResourceRequir ement::equals(

constcse::Resou rceRequirement & rhs={...}) Line 27 C++
mscorwks.dll!79 25c098()
^^^^^^^^^^^^^^^ ^^^^ probable culprit ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^
libjss.dll!utl: :equals<cse::Re sourceRequireme nt>(
cse::ResourceRe quirement* lhs = 0x07455b48,
cse::ResourceRe quirement* rhs = 0x07455b98) Line 134 + 0x15
bytes C++
libjss.dll!jss. ResourceRequire ment.Equals(
System.Object rhs = 0x04ce6ba0)
Line 33 + 0xc bytes C++
demo_cs.exe!dem o_cs.demo_cs.ev ilBug() Line 143 + 0x9 bytes C#
demo_cs.exe!dem o_cs.demo_cs.Ma in(string[] args = {Length=5})
Line 317 C#

////////////////////////////////////////////////////////////////

The register mangling must occur in mscorwks.dll, which I assume is
responsible for managing calls from managed into unmanaged code. I
found that if I compiled the native C++ projects with /CLR switch,
then the problem goes away (because there is no longer a transition
into unmanaged code). However, compiling with "/CLR" has significant
disadvantages, including:

1. can't use pre-compiled headers -- they make a BIG difference
compilation performance
2. debugging of unmanaged code becomes very difficult

I should say that I have followed the instructions for mixed-mode DLLs
that are described in a KB article called "Converting Managed
Extensions for C++ Projects from Pure Intermediate Language to Mixed
Mode".

The debugging problem when using "/CLR" _also_ implicates
mscorwks.dll. Basically when I step into unmanaged C++ code, the
debugger says "there is no source code for the current location".
Looking at the call stack, I can see that mscorwks.dll!79 25c098 is on
TOP of the call stack, and
the native C++ code that I am trying to debug is next down on the call
stack. The end result is that debugging the native C++ code (that was
compiled with "/CLR") is a very painful exercise.

So I have to choose between:

a) having my code execute as I wrote it ("/CLR" switch turned
ON for native C++)
-OR-
b) being able to debug the code ("/CLR" switch turned OFF for
native C++)

In other words, if I want to be able to debug the code, then I must
accept the fact that the code will not always execute as I wrote it.
Not a good situation to be in! I don't see what I can do now except
try to get help.

Please ... help ....

-Adam McKee // sp**@adam-mckee.net

Nov 16 '05 #2
Adam McKee wrote:
virtual bool returnsFalse() const;


Yes, indeed this is a known bug for over 1 year!!!
I reported it 12.04.2002.

See also:
http://groups.google.de/groups?threa...FOgiRDHA.2020%
40TK2MSFTNGP11. phx.gbl

There are also some possible workarounds for this bug.

--
Greetings
Jochen

Do you need a memory-leak finder ?
http://www.codeproject.com/useritems/leakfinder.asp
Nov 16 '05 #3
Jochen Kalmbach wrote:
Adam McKee wrote:
virtual bool returnsFalse() const;


Yes, indeed this is a known bug for over 1 year!!!
I reported it 12.04.2002.


Has it been reported through a formal channel, or just on the ngs? This is
definitely something that would be nice to get fixed!

-cd
Nov 16 '05 #4
Carl Daniel [VC++ MVP] wrote:
Jochen Kalmbach wrote:
Adam McKee wrote:
virtual bool returnsFalse() const;


Yes, indeed this is a known bug for over 1 year!!!
I reported it 12.04.2002.


Has it been reported through a formal channel, or just on the ngs?
This is definitely something that would be nice to get fixed!


Yes, this bug is known to the VC team and AFIAK will be fixed a future
release of the product.

-cd
Nov 16 '05 #5
Carl Daniel [VC++ MVP] wrote:
Jochen Kalmbach wrote:
Adam McKee wrote:
virtual bool returnsFalse() const;


Yes, indeed this is a known bug for over 1 year!!!
I reported it 12.04.2002.


Has it been reported through a formal channel, or just on the ngs?
This is definitely something that would be nice to get fixed!


It was reported to MS support hotline with the Support-ID: SRD020412600033

--
Greetings
Jochen

Do you need a memory-leak finder ?
http://www.codeproject.com/useritems/leakfinder.asp
Nov 16 '05 #6

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

Similar topics

2
2398
by: entoone | last post by:
I have a field called pword, whenever someone enters anything but numeric, i.e. mixed alpha with numeric, or even just alpha.. the following error appears. Warning: mysql_numrows(): supplied argument is not a valid MySQL result resource What do I need to change the field to, to be able to have whatever password configuration the user wants to enter?
34
4474
by: Niels Berkers | last post by:
Hi, i'd like to host my web pages using multiparts to reduce the number of hits on the server. i know this isn't a real PHP subject, but i'll try it anyway. i've been searching the web for solutions and examples with no succes. does anybody know a good starting point hints / tips are also welcome Regards
3
2574
by: Perttu Pulkkinen | last post by:
No questions, but just consider if this is useful to you:-) but of course feedback & corrections are welcome. function php_mixed_to_js_value($jsname, $mixed) { if(is_null($mixed)) { return "\n $jsname = null;\n"; } elseif(is_string($mixed)) { return "\n $jsname = '$mixed';\n"; } elseif(is_numeric($mixed) || is_boolean($mixed))
0
1780
by: Swaroop Kumar | last post by:
Hi: I'm trying to write a schema that contains information as described below: 1. The first element is a mandatory fixed string. 2. The second element is a mixed content element that can contain multiple occurrences of two possible elements interspersed with regular text.
2
1766
by: Paul A. Hoadley | last post by:
Hello, I am trying to convert a RELAX NG schema to DTD using Trang. I am currently trying to add some inline elements to the schema, such as <emph> for marking emphasised text. Here is an excerpt from the schema: <define name="description"> <element name="description"> <mixed>
15
5418
by: Bill Cohagan | last post by:
I'm trying to generate class definitions from an XSD that contains something like: <xs:complexType name="foo" mixed="true"> <xs:choice minOccurs = "0" maxOccurs="unbounded"> <xs:element name = "bar" type = "something"/> ... <xs:element name = "baz" type = "somethingelse"/> </xs:choice> </xs:complexType>
5
5771
by: Jeff | last post by:
I am trying to crete a method that will convert an improper fraction to a mixed number... I am not sure how about how to acomplish this. I know I can get the remainder with the modulus operator (%), but I am not sure how to get the quotent. any insight would be appreciated. thanks
0
1612
by: Garrek | last post by:
I have an existing ASP.Net application that must be modified to support mixed content: Latin-based languages (i.e. English) intermixed with Arabic. Our code and database assumes everything is UTF-8. I have some concerns on this and would appreciate feedback. 1) Displaying the english content requires left-to-right formatting ( left justified) while arabic content requirese right-to-left (right justified). Is there a way to determine...
2
1601
by: bearophileHUGS | last post by:
Notes: - This email is about Mark Dufour's Shed Skin (SS) (http://shed-skin.blogspot.com), but the errors/ingenuousness it contains are mine. My experience with C++ is limited still. - The following code comes from a discussion with Mark. One of the purposes of SS is to produce fast-running programs (compiling a subset of Python code to C++), to do this it accepts some compromises in the type flexibility used by the programs, at the...
4
10296
by: natG | last post by:
Hi; I am transferring data from MySql to db2 using my own java/jdbc program. Working out ok, except for the fact that our apps use mixed-case names for tables and columns. Although my CREATE TABLE commands issued via jdbc uses mixed case for the names, db2 insists on using only upper case. (This also happens from the CLP or DB2CC, but my concern is for it to work via jdbc.) Is there a simple setting at the database level to allow mixed...
0
9592
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9425
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10058
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8886
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7416
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6678
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5450
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3576
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2817
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 can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.