473,387 Members | 1,925 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Bool return value changing magically from unmanaged to managed function call.

Hi, I have a c# application that needs to access c++ libraries, so it
does this by using a managed layer of c++ CLI.

Anyway, in the CLI function call, that calls the unmanaged function it
expects a boolean return value, which it gets, but the value changes!
I walked throuhg the code, and the unmanged code is returning false,
but when I look at the variable in the managed code it's return value
it true. Even after I initialized the variable accepting that value
as false. There are no other threads accesing this code. Anyone have
any ideas?

Feb 7 '07 #1
16 2567
"DaTurk" <mm******@hotmail.comwrote in message
news:11**********************@l53g2000cwa.googlegr oups.com...
Anyway, in the CLI function call, that calls the unmanaged function it
expects a boolean return value, which it gets, but the value changes!
I walked throuhg the code, and the unmanged code is returning false,
but when I look at the variable in the managed code it's return value
it true. Even after I initialized the variable accepting that value
as false. There are no other threads accesing this code. Anyone have
any ideas?
It's a bug in the way the runtime marshals and unmarshals booleans across
the boundary between native and managed code.

There are other ways of solving the problem, but this one

bool unManagedFunction(...)
{
bool ok;

// set ok

ok = ...;

// Insure the 3 high order bytes of the accumulator will be zero
// Then set its low order byte appropriately

_asm xor eax, eax
return ok;
}

imposes a single instruction penalty.

Regards,
Will
www.ivrforbeginners.com

Feb 7 '07 #2
On Feb 7, 9:16 am, "William DePalo [MVP VC++]"
<willd.no.s...@mvps.orgwrote:
"DaTurk" <mmagd...@hotmail.comwrote in message

news:11**********************@l53g2000cwa.googlegr oups.com...
Anyway, in the CLI function call, that calls the unmanaged function it
expects a boolean return value, which it gets, but the value changes!
I walked throuhg the code, and the unmanged code is returning false,
but when I look at the variable in the managed code it's return value
it true. Even after I initialized the variable accepting that value
as false. There are no other threads accesing this code. Anyone have
any ideas?

It's a bug in the way the runtime marshals and unmarshals booleans across
the boundary between native and managed code.

There are other ways of solving the problem, but this one

bool unManagedFunction(...)
{
bool ok;

// set ok

ok = ...;

// Insure the 3 high order bytes of the accumulator will be zero
// Then set its low order byte appropriately

_asm xor eax, eax
return ok;

}

imposes a single instruction penalty.

Regards,
Willwww.ivrforbeginner
THanks for the reply. I'm not entirely sure I understand this command
_asm xor eax, eax enough to use it, would you mind elaborating on it?
In the unmanaged code, it already uses a similar command, how will the
one you propose effect this one __asm mov eax,100?? Or is this the
problem?

Feb 7 '07 #3
Just a heads up, I used that command _asm xor eax, eax, and removed
the other one, and it didn't help. What are some of the other
solutions?

Feb 7 '07 #4
"DaTurk" <mm******@hotmail.comwrote in message
news:11**********************@s48g2000cws.googlegr oups.com...
THanks for the reply.
You are welcome.
I'm not entirely sure I understand this command
_asm xor eax, eax enough to use it, would you mind
elaborating on it?
It sets the value of the 32 bit accumulator register (EAX) to 0. C/C++
functions whose return values fit into 32 bits are returned to the caller in
EAX.

Now where you have native code that looks like this

bool a = boolFunc();

if ( a )
{
}

the function sets only the low order byte and the if statement checks only
the low byte. All is well.

However, across the managed / native boundary I _think_ that booleans are
larger than a single byte. So whatever random garbage you have in the some
or all of the three high order bytes of a function's return value get passed
back to the caller. If they are not all 0, you get a bogus TRUE value.
In the unmanaged code, it already uses a similar command, how will the
one you propose effect this one __asm mov eax,100?? Or is this the
problem?
IIUC, that will return TRUE. Is that want you want?

One way or another you probably want to clear the high 3 bytes of EAX and
drop the return value into the low byte. You can change all the return
values of your boolean functions from bool (1 byte) to BOOL (4 bytes) which
will do the trick, you can do what I do, or you can do as a knowledge base
article suggests and call a function which returns 0 to EAX _immediately_
before the real return.

Regards,
Will
www.ivrforbeginners.com
Feb 7 '07 #5
On Feb 7, 9:51 am, "William DePalo [MVP VC++]"
<willd.no.s...@mvps.orgwrote:
"DaTurk" <mmagd...@hotmail.comwrote in message

news:11**********************@s48g2000cws.googlegr oups.com...
THanks for the reply.

You are welcome.
I'm not entirely sure I understand this command
_asm xor eax, eax enough to use it, would you mind
elaborating on it?

It sets the value of the 32 bit accumulator register (EAX) to 0. C/C++
functions whose return values fit into 32 bits are returned to the caller in
EAX.

Now where you have native code that looks like this

bool a = boolFunc();

if ( a )
{
}

the function sets only the low order byte and the if statement checks only
the low byte. All is well.

However, across the managed / native boundary I _think_ that booleans are
larger than a single byte. So whatever random garbage you have in the some
or all of the three high order bytes of a function's return value get passed
back to the caller. If they are not all 0, you get a bogus TRUE value.
In the unmanaged code, it already uses a similar command, how will the
one you propose effect this one __asm mov eax,100?? Or is this the
problem?

IIUC, that will return TRUE. Is that want you want?
What do you mean that this will return true? Do you mean that because
of this statement, no matter what, the function will return true?
>
One way or another you probably want to clear the high 3 bytes of EAX and
drop the return value into the low byte. You can change all the return
values of your boolean functions from bool (1 byte) to BOOL (4 bytes) which
will do the trick, you can do what I do, or you can do as a knowledge base
article suggests and call a function which returns 0 to EAX _immediately_
before the real return.

Regards,
Willwww.ivrforbeginners.com

Feb 7 '07 #6
"DaTurk" <mm******@hotmail.comwrote in message
news:11*********************@a34g2000cwb.googlegro ups.com...
Just a heads up, I used that command _asm xor eax, eax, and removed
the other one, and it didn't help. What are some of the other
solutions?
You'll find more wordy explanations here:

http://www.codeproject.com/buglist/virtualboolbug.asp

http://support.microsoft.com/default.aspx?kbid=823071

But, if it is the bug I think it is then the crux of the issue is that some
number of the high 24 bits of EAX are set on return.

You can check that in the debugger. Put a breakpoint on the right brace that
ends your boolean function. When your application stops there take a look at
EAX. If it is larger than 0x000000FF you failed to clear the high order 24
bits. The

_asm xor eax, eax

instruction clears all 32 of them and if you put it _just before_ the place
in your code where you return the boolean value, that return should set
_only_ the low order eight bits.

Regards,
Will
www.ivrforbeginners.com
Feb 7 '07 #7
On Feb 7, 10:28 am, "William DePalo [MVP VC++]"
<willd.no.s...@mvps.orgwrote:
"DaTurk" <mmagd...@hotmail.comwrote in message

news:11*********************@a34g2000cwb.googlegro ups.com...
Just a heads up, I used that command _asm xor eax, eax, and removed
the other one, and it didn't help. What are some of the other
solutions?

You'll find more wordy explanations here:

http://www.codeproject.com/buglist/virtualboolbug.asp

http://support.microsoft.com/default.aspx?kbid=823071

But, if it is the bug I think it is then the crux of the issue is that some
number of the high 24 bits of EAX are set on return.

You can check that in the debugger. Put a breakpoint on the right brace that
ends your boolean function. When your application stops there take a look at
EAX. If it is larger than 0x000000FF you failed to clear the high order 24
bits. The

_asm xor eax, eax

instruction clears all 32 of them and if you put it _just before_ the place
in your code where you return the boolean value, that return should set
_only_ the low order eight bits.

Regards,
Willwww.ivrforbeginners.com
Your right, at the end of the function the
EAX 0x1000b300 unsigned long

Feb 7 '07 #8
But here's something interesting.

I run the program with _asm xor eax, eax in it. stepping through it.
After this line I see the Eax go to 0, then the next line is the
return statement. I step onto the return statement, and when I step
again, it steps onto the return statement again, you know you have to
step twice to get off of the statement, and on that second step the
EAX gets garbled again. Any insights as to why it would take two
steps to get passed the return statement?

Feb 7 '07 #9
"DaTurk" <mm******@hotmail.comwrote in message
news:11********************@v45g2000cwv.googlegrou ps.com...
I run the program with _asm xor eax, eax in it. stepping through it.
After this line I see the Eax go to 0, then the next line is the
return statement. I step onto the return statement, and when I step
again, it steps onto the return statement again, you know you have to
step twice to get off of the statement, and on that second step the
EAX gets garbled again. Any insights as to why it would take two
steps to get passed the return statement?
I suggest that you put a breakpoint at the entry to your function and switch
to the disassembly view in the IDE. Then single step through the machine
code, not the source code. That should tell you exactly what is going on.

Regards,
Will
www.ivrforbeginners.com
Feb 7 '07 #10
On Feb 7, 11:02 am, "William DePalo [MVP VC++]"
<willd.no.s...@mvps.orgwrote:
"DaTurk" <mmagd...@hotmail.comwrote in message

news:11********************@v45g2000cwv.googlegrou ps.com...
I run the program with _asm xor eax, eax in it. stepping through it.
After this line I see the Eax go to 0, then the next line is the
return statement. I step onto the return statement, and when I step
again, it steps onto the return statement again, you know you have to
step twice to get off of the statement, and on that second step the
EAX gets garbled again. Any insights as to why it would take two
steps to get passed the return statement?

I suggest that you put a breakpoint at the entry to your function and switch
to the disassembly view in the IDE. Then single step through the machine
code, not the source code. That should tell you exactly what is going on.

Regards,
Willwww.ivrforbeginners.com
Sounds like a good idea, I started loking at it, when I realized the
last itme I looked at assembly was about 15 years ago, and I sucked at
it then. WOuld you mind taking a peek at it? This is right at the
end of the function.

1000B3BA call _RTC_CheckEsp (10028A20h)
//__asm mov eax,100
_asm xor eax, eax;
1000B3BF xor eax,eax
return false;
1000B3C1 mov byte ptr [ebp-2ADh],0
1000B3C8 mov byte ptr [ebp-4],0Ch
1000B3CC mov esi,esp
1000B3CE lea ecx,[err]
1000B3D4 call dword ptr
[__imp_std::basic_string<char,std::char_traits<char >,std::allocator<char>
>::~basic_string<char,std::char_traits<char>,std:: allocator<char
(1003007Ch)]
1000B3DA cmp esi,esp
1000B3DC call _RTC_CheckEsp (10028A20h)
1000B3E1 mov eax,offset $L84050 (1000B3E7h)
1000B3E6 ret
$L84050:
1000B3E7 mov al,byte ptr [ebp-2ADh]
}
}

Thanks again

Feb 7 '07 #11
"DaTurk" <mm******@hotmail.comwrote in message
news:11**********************@q2g2000cwa.googlegro ups.com...
Sounds like a good idea, I started loking at it, when I realized the
last itme I looked at assembly was about 15 years ago, and I sucked at
it then. WOuld you mind taking a peek at it? This is right at the
end of the function.
OK.
1000B3BA call _RTC_CheckEsp (10028A20h)
//__asm mov eax,100
_asm xor eax, eax;
1000B3BF xor eax,eax
return false;
1000B3C1 mov byte ptr [ebp-2ADh],0
1000B3C8 mov byte ptr [ebp-4],0Ch
1000B3CC mov esi,esp
1000B3CE lea ecx,[err]
1000B3D4 call dword ptr
[__imp_std::basic_string<char,std::char_traits<char >,std::allocator<char>
>>::~basic_string<char,std::char_traits<char>,std: :allocator<char
(1003007Ch)]
1000B3DA cmp esi,esp
1000B3DC call _RTC_CheckEsp (10028A20h)
1000B3E1 mov eax,offset $L84050 (1000B3E7h)
1000B3E6 ret
$L84050:
1000B3E7 mov al,byte ptr [ebp-2ADh]
}
}
It may be that the destructor for an "automatic" std::string object runs
just after my

_asm xor eax, eax

and before the actual

ret

leaving EAX non-zero. You can step through the assembly code to find out.

If that's the case you can either dynamically allocate it and delete it
before the xor (that's nasty and brittle) or change the return type to BOOL
or int.

Perhaps someone else has a better alternative.
Thanks again
You are welcome.

Regards,
Will
www.ivrforbeginners.com
Feb 7 '07 #12
Hi DaTurk,

"DaTurk" <mm******@hotmail.comwrote in message
news:11**********************@l53g2000cwa.googlegr oups.com...
Hi, I have a c# application that needs to access c++ libraries, so it
does this by using a managed layer of c++ CLI.
Just to avoid misunderstandings, can you please confirm you are using
C++/CLI (Visual Studio 2005) and no earlier version.

Marcus
Feb 7 '07 #13

"William DePalo [MVP VC++]" <wi***********@mvps.orgwrote in message
news:eD**************@TK2MSFTNGP06.phx.gbl...
"DaTurk" <mm******@hotmail.comwrote in message
news:11**********************@q2g2000cwa.googlegro ups.com...
>Sounds like a good idea, I started loking at it, when I realized the
last itme I looked at assembly was about 15 years ago, and I sucked at
it then. WOuld you mind taking a peek at it? This is right at the
end of the function.

OK.
>1000B3BA call _RTC_CheckEsp (10028A20h)
//__asm mov eax,100
_asm xor eax, eax;
1000B3BF xor eax,eax
return false;
1000B3C1 mov byte ptr [ebp-2ADh],0
1000B3C8 mov byte ptr [ebp-4],0Ch
1000B3CC mov esi,esp
1000B3CE lea ecx,[err]
1000B3D4 call dword ptr
[__imp_std::basic_string<char,std::char_traits<char >,std::allocator<char>
>>>::~basic_string<char,std::char_traits<char>,std ::allocator<char
(1003007Ch)]
1000B3DA cmp esi,esp
1000B3DC call _RTC_CheckEsp (10028A20h)
1000B3E1 mov eax,offset $L84050 (1000B3E7h)
1000B3E6 ret
$L84050:
1000B3E7 mov al,byte ptr [ebp-2ADh]
}
}

It may be that the destructor for an "automatic" std::string object runs
just after my

_asm xor eax, eax

and before the actual

ret

leaving EAX non-zero. You can step through the assembly code to find out.

If that's the case you can either dynamically allocate it and delete it
before the xor (that's nasty and brittle) or change the return type to
BOOL or int.

Perhaps someone else has a better alternative.
You can force the stack destructor to run early using an extra enclosing
scope "{}". However, use of inline assembly to adjust EAX is brittle. You
should make the managed and unmanaged definitions match, both one byte (C++
bool and C# byte) or four byte (C++ BOOL and C# int). Relying on nothing
else to touch EAX is a very bad idea, and there are some calling conventions
where EAX isn't used for the return value.
>
>Thanks again

You are welcome.

Regards,
Will
www.ivrforbeginners.com


Feb 7 '07 #14
"Ben Voigt" <rb*@nospam.nospamwrote in message
news:ea**************@TK2MSFTNGP02.phx.gbl...
However, use of inline assembly to adjust EAX is brittle.
Well, life is full of compromises. Like a lot of people I encountered the
bug well after my API was designed. I could have gone back and changed all
of the signatures of the boolean functions but for me and my application it
was far less risky to add a single line immediately before the single return
instruction in all of the functions. YMMV.
You should make the managed and unmanaged definitions match, both one byte
(C++ bool and C# byte)
For me, when I think bool I think binary I think on/off, yes/no, true/false.
When I think byte I think small number. As I see it, this is a case of the
cure being worse than the disease. YMMV.
or four byte (C++ BOOL and C# int).
As above.
and there are some calling conventions where EAX isn't used for the return
value.
Hmm. I didn't know that. Under what conditions does a bool return value not
get returned in EAX?

Regards,
Will
Feb 7 '07 #15
On Feb 7, 12:44 pm, "Marcus Heege" <nos...@heege.netwrote:
Hi DaTurk,

"DaTurk" <mmagd...@hotmail.comwrote in message

news:11**********************@l53g2000cwa.googlegr oups.com...
Hi, I have a c# application that needs to access c++ libraries, so it
does this by using a managed layer of c++ CLI.

Just to avoid misunderstandings, can you please confirm you are using
C++/CLI (Visual Studio 2005) and no earlier version.

Marcus
My apologies, I'm using Mnaged C++, .net 1.1.

Feb 7 '07 #16
"DaTurk" <mm******@hotmail.comwrote in message
news:11**********************@v45g2000cwv.googlegr oups.com...
On Feb 7, 12:44 pm, "Marcus Heege" <nos...@heege.netwrote:
>Hi DaTurk,

"DaTurk" <mmagd...@hotmail.comwrote in message

news:11**********************@l53g2000cwa.googleg roups.com...
Hi, I have a c# application that needs to access c++ libraries, so it
does this by using a managed layer of c++ CLI.

Just to avoid misunderstandings, can you please confirm you are using
C++/CLI (Visual Studio 2005) and no earlier version.

Marcus

My apologies, I'm using Mnaged C++, .net 1.1.
OK. Now it makes sense. The bug you discribe is very likely the one Wiliam
DePalo has mentioned. Have you solved the problem now?
Feb 7 '07 #17

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

Similar topics

13
by: Daniel Jin | last post by:
I read somewhere that a bool is 1 byte unless if it's in a array, then it will be 2 bytes. is that true? if so, any explaination to why that is?
5
by: Gernold Schneider | last post by:
I have a managed code function calling a unmanaged code function which returns a "bool". Obviously the return value is always "true", if i am not running the code in the debugger. If i run the...
2
by: Ian | last post by:
When I have an unmanaged class (compiled without /clr or with #pragma unmanaged) with return type virtual bool, the return value always comes out true when called in managed code. Only happens...
10
by: Mark Jerde | last post by:
I'm trying to learn the very basics of using an unmanaged C++ DLL from C#. This morning I thought I was getting somewhere, successfully getting back the correct answers to a C++ " int SumArray(int...
2
by: joye | last post by:
Hello, My question is how to use C# to call the existing libraries containing unmanaged C++ classes directly, but not use C# or managed C++ wrappers unmanaged C++ classes? Does anyone know how...
12
by: Howard Kaikow | last post by:
In the code below, ALL the lines that start with PPTfile << are getting the following error at build time. "//i:\C++\C++Code\FileOperations\Form1.h(127) : warning C4800: 'System::String __gc *'...
1
by: Bern McCarty | last post by:
What do you make of this? I cannot tell for sure but it almost seems as the the transition thunk to get back from the native bool method to the managed caller is looking at eax and, if any bit is...
3
by: markb | last post by:
Hi My C# app is being called from a callback from an unmanaged DLL. One of the parameters of the callback is of type BOOL. I am using PInvoke to marshal this to a (managed) bool. The problem is...
6
by: Aston Martin | last post by:
Hi All, ********************** My Situation ********************** I am working on project that involves passing a structure to unmanaged code from .Net world (well using C#). Perhaps an example...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
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...

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.