FatalExecutionEngineError while calling dll method - c#

In my program on this line:
int value = MTEConnect(auth_string, err);
I receive such exeption:
FatalExecutionEngineError
The runtime has encountered a fatal error. The address of the
error was at 0x68c8a681, on thread 0x2334. The error code is
0xc0000005. This error may be a bug in the CLR or in the unsafe
or non-verifiable portions of user code. Common sources of this
bug include user marshaling errors for COM-interop or PInvoke,
which may corrupt the stack.
MTEConnect is imported such a way:
[DllImport("mtesrl.dll", CharSet = CharSet.Ansi)]
private static extern int MTEConnect(String pars, StringBuilder err);
What's the problem and how to fix it?
upd: I can reproduce the same problem on another machine, but I got a little more desriptive message:
Managed Debugging Assistant 'FatalExecutionEngineError' has detected a problem in 'C:\blahblah\MBClient\bin\Debug\MBClient.vshost.exe
Library itself is functional, because it can be used from another applications, I just can't use it from c#

I have solved my problem!
Code doesn't work this way:
StringBuilder err = new StringBuilder();
int value = MTEConnect(auth_string, err);
But it do work this way:
StringBuilder err = new StringBuilder(100);
int value = MTEConnect(auth_string, err);
It seems buffer was too short.

A FatalExecutionEnigneError is often the result of corruption within the core CLR native code that leads to a fatal native exception. When it occurs at the site of a PInvoke call it's a big indicator the PInvoke signature is incorrect.
Could you provide the native signature so we can help diagnose this problem?

Related

How to safely pass string reference from c# to c++?

I am developing a C# dll project with C++ dll project.
Let's say that C++ dll logins to a certain web site, and do some query on the web server.
And C++ dll has to return that html code of a web site.
In the same time, C++ dll must save the cookie data from the web site.
So, I passed StringBuilder object to C++ function.
I already know how to get html code from a web site using HttpWebRequest and HttpWebResponse classed in C#, but unfortunately I have to do it in C++ dll project.
So bear in mind, I don't need any C# codes.
I have tried Passing a string variable as a ref between a c# dll and c++ dll.
Passing StringBuilder from C# and get it as LPTSTR.
It works fine, but some strings were missing from the result.
I couldn't find out the reason.
Anyway, here is my code.
C++
extern "C" __declspec(dllexport) BSTR LoginQuery(const char* UserID, const char* UserPW, char Cookies[])
{
std::string html;
try
{
std::map<std::string, std::string> cookies;
MyClass *myclass = new MyClass();
html = myclass->LoginQuery(UserID, UserPW, cookies);
// Response cookies
std::string cookieData;
for (std::map<std::string, std::string>::iterator iterator = cookies.begin(); iterator != cookies.end(); iterator++)
{
cookieData += iterator->first;
cookieData += "=";
cookieData += iterator->second;
cookieData += ";";
}
sprintf(Cookies, cookieData.c_str(), 0);
delete myclass;
}
catch (...)
{
}
return ::SysAllocString(CComBSTR(html.c_str()).Detach());
}
C#
[DllImport(#"MyDll.dll", EntryPoint="LoginQuery", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern void LoginQuery(string UserID, string UserPW, StringBuilder Cookies);
void SomeThing()
{
StringBuilder _cookies = new StringBuilder(1024);
string result = LoginQuery("test", "1234", _cookies);
}
It works fine.
With the StringBuilder as cookie, I can carry on the next url of the web site.
(I am using libcurl in C++ project.)
But the problem is that I have about 100 ids.
When it runs about 3~40, it returns heap error.
Debug Assertion Failed!
Program: ~~~~mics\dbgheap.c
Line: 1424
Expression: _pFirstBlock == pHead
I cannot click the abort, retry or ignore button.
It looks like C# application hangs.
I read so many articles about debug assertion failed with dbgheap.
Mostly like free memory object from another heap.
I am newbie to C++.
I read Edson's question on http://bytes.com/topic/c-sharp/answers/812465-best-way-interop-c-system-string-c-std-string.
But the error does not always comes out in certain time.
So I came across with a guess, that it happens when .NET runs garbage collector.
.NET garbage collector tries to free some memory which created from C++ dll and I get the heap error.
Am I right?
I think he's suffering same problem as mine.
What is the best way to avoid heap error and return correct string from C++ dll to C# dll?
P/S: And the heap error occurs only when I run it debug mode. I don't get the error when I run release mode.
EDIT
According to WhozCraig answer, I changed my code as below.
//return ::SysAllocString(CComBSTR(html.c_str()).Detach());
CComBSTR res(html.c_str());
return res.Detach();
But no luck, I still get the heap error.
Your question is title asks about passing a string reference from c# to c++, but later in the text you ask how to return a string from C++ to C#. Also, you tell you are new to C++. With this in mind, I'll tell how I did this sort of interaction last time I had to do that. I just made C++ side allocate and free all the memory, passing out to C# only IntPtrs to be Marshal.PtrToStringAnsi(p)ed. In my case, storing recerences thread-local in C++ and freeing them on each function call was enough, but you can make a C++ function that frees whatever ref it is given. Not very intellectual and not necessarily the most efficient way, but it works.
upd:
It does just what they say it does. Some quick googling comes up with this article. I think it's pretty good, so you can refer to it instead of my suggestion. Passing raw IntPtrs is good if the pointer is not okay to be freed by itself (like old Delphi/C++Builder style strings, for example) and you prefer to be bothered more on the managed side than on the native side.
As an example, piece of code doing Delphi interaction (good for C++ Builder as well):
// function Get_TI_TC(AuraFileName:PAnsiChar; var TI,TC:PAnsiChar):Boolean; stdcall; external 'AuraToIec104.dll' name 'Get_TI_TC';
[DllImport("AuraToIec104")]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool Get_TI_TC(string AuraFileName, out IntPtr TI, out IntPtr TC);
public static bool Get_TI_TC(string AuraFileName, out string TI, out string TC)
{
IntPtr pTI, pTC;
bool result = Get_TI_TC(AuraFileName, out pTI, out pTC);
TI = Marshal.PtrToStringAnsi(pTI);
TC = Marshal.PtrToStringAnsi(pTC);
return result;
}
It looks like your problem is rather simple. You are creating a StringBuilder that can hold as much as 1024 chars. If your C++ function returns more than that, your application will crash (sooner or later).
So to fix your problem, increase the StringBuilder's size to the maximum possible output length. More details: Passing StringBuilder to PInvoke function which quotes:
The only
caveat is that the StringBuilder must
be allocated enough space for the
return value, or the text will
overflow, causing an exception to be
thrown by P/Invoke.
It might actually be better in your case with dynamic string lengths to use a BSTR parameter in the C++ function. You can then use [MarshalAs(UnmanagedType.AnsiBStr), Out] ref string ... in C# and BSTR* in C++.

COM interface modifications have suddenly started causing exceptions

A couple of years ago I inherited a C# app that uses COM objects defined in an unmanaged C++ DLL. I've been successfully tweaking the object interfaces ever since, but following a (possibly irrelevant) VS2012 upgrade, function signature additions and changes are suddenly being punished by random exceptions such as ExecutionEngineException and SEHException.
My understanding was that the app uses registration-free COM. There's no DLLRegisterServer implementation, and I see no mention of the interface guids in the registry, just one in C#...
[ComImport,
Guid("C2427CB1-D6AE-49e8-B266-114F981C3353"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
SuppressUnmanagedCodeSecurity()]
public interface IDC
{
and one in a C++ header.
interface __declspec(uuid("C2427CB1-D6AE-49e8-B266-114F981C3353"))
IDC : IUnknown
{
To be sure though, I decided to swap a new guid into these two places, and discovered that it stopped C# from recognizing the class at all:
System.InvalidCastException
Unable to cast COM object of type 'System.__ComObject' to interface type 'Apx.IDC'.
This operation failed because the QueryInterface call on the COM component for the
interface with IID '{the new guid}' failed due to the following error:
No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
(The above error is apparently often caused by mixing appartment states, but swapping a guid doesn't cause that). So I deduce there must be additional relevant detail somewhere that's conflicting with my changes. But where might that somewhere be? Thanks for reading...
Edit:
An example exception is...
First-chance exception at 0x000007feec748be4 (clr.dll) in Apex.exe: 0xC0000005:
Access violation reading location 0xffffffffffffffff.
The Common Language Runtime cannot stop at this exception. Common causes include:
incorrect COM interop marshalling, and memory corruption. To investigate further,
using native-only debugging.
An unhandled exception of type 'System.ExecutionEngineException' occurred in Apex.exe
for
[PreserveSig] [return: MarshalAs(UnmanagedType.I1)]
bool LoadDisplayList(IntPtr fileHandle, IntPtr pDisplayList,
UInt16 version, IntPtr pComparison);
and
virtual bool __stdcall LoadDisplayList(HANDLE fileHandle, class CDisplayList * pDisplayList,
WORD version, CDisplayList * pComparison) = 0;
with a stack trace ending
[Native to Managed Transition]
Apex.Graphics64.dll!CDisplayList::LoadRenderRecs(void * f=0x000000000000056c, CDisplayList * pComparison=0x0000000023ad2cf0) Line 1772 C++
Apex.Graphics64.dll!CDisplayList::Load(void * f=0x000000000000056c, unsigned short version=0x0002, CDisplayList * pComparison=0x0000000023ad2cf0) Line 1845 + 0x26 bytes C++
Apex.Graphics64.dll!CBaseDC::LoadDisplayList(void * f=0x000000000000056c, CDisplayList * pList=0x0000000023ad2cf0, unsigned short version=0x0002, CDisplayList * pComparison=0x0000000023ad2cf0) Line 1896 + 0x33 bytes C++
[Managed to Native Transition]
Apex.exe!Apex.DDC.LoadDisplayList(System.IO.FileStream file = {System.IO.FileStream}, Apex.DisplayList displayList = {Apex.DisplayList}, ushort version = 0x0002, Apex.DisplayList comparison = null) Line 1124 + 0xaf bytes C#
Apex.exe!Apex.DisplayList.Load(System.IO.FileStream f = {System.IO.FileStream}, ushort loadVersion = 0x0002, Apex.INode stubsRoot = {Apex.ViewPort3D}, Apex.DisplayList comparison = null) Line 166 + 0x53 bytes C#
The exact crash point varies somewhat - here it actually managed to get inside LoadDisplayList(), which is better than usual. As the crash suggests heap damage, I've tried stripping the function's signature down to a parameterless void return, reduced its contents to a trace, and called it right after the object's creation - still to get a crash. The same function doesn't crash if I move it to the top of the definitions, in which case some other interface function crashes out instead, leading me to think it's more likely to be a COM problem than algorithm-level memory corruption.
I think I've fixed the problem. Once I was able to step into the DLL a little, a popup saying that the source didn't match the executable led me to investigate another longstanding but previously unproblematic quirk, that the DLL's Linker / General / Output File wasn't inside the project's General / Output Directory (warning MSB8012). After cleaning up this anomaly I was able change the guid successfully, so it seems VS2012 uses these settings slightly differently to older versions. The moral...don't let warnings hang around.

"Win32Exception: The operation completed successfully" after WTSQueryUserToken on 32bit Windows (64bit works)

I'm developing a small Windows Service in C# that needs to do interop with Win32 API at some point. I'm getting the following exception which does not make sense to me:
System.ComponentModel.Win32Exception: The operation completed successfully
Right after the last line in this C# snippet:
var sessionId = Kernel32.WTSGetActiveConsoleSessionId();
var userTokenPtr = new IntPtr();
if (!WtsApi32.WTSQueryUserToken(sessionId, out userTokenPtr))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
Here's how I'm declaring WTSQueryUserToken in WtsApi32:
[DllImport("Wtsapi32.dll", EntryPoint="WTSQueryUserToken")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WTSQueryUserToken
(
[In, MarshalAs(UnmanagedType.U8)] ulong sessionId,
[Out] out IntPtr phToken
);
Some facts:
This works perfectly on 64bit Win7, but fails on a 32bit Win7.
There's no way the 10,000 handle limit has been reached when this is executed, it's the first Win32 call in a very small windows service.
I think there might be some underlying Win32 error but some bug overwrote the errorcode with a 0, thus giving me the "success" error message, but I don't know how to confirm or even diagnose this.
When I catch the exception, sessionId is 1 and userTokenPtr is 0. However, GetLastError returns 0 so I have no idea what happened.
Nearly all of the answers I found to this problem had to do with improper disposal of user controls. Since this is a Windows service, this is not the case.
I'm guessing there must be something wrong with my WTSQueryUserToken declaration, since it only fails on 32bit Windows, which leads me to think it's a marshaling problem. However, I still can't see what it might be.
Your sessionId parameter us defined as a c# ulong - an unsigned 64-bit integer, whereas the actual function export is expecting a Win32 ulong - an unsigned 32-bit integer.
c# ulong data type
Win32 data types

Mapping IntPtr into Struct via Marshal.PtrToStructure causing "Access Violation Exception"

I'm trying to use a C++ DLL (3rd party library implementing EMI protocol, having source code available) in .NET. I've succesfully done marshalling, calling the functions and getting everything work fine.
The problem occurs when I want to do marshalling from IntPtr back into the .NET Struct , here's the code (modified as suggested - removed "ref" and changed the AllocHGlobal to allocate just size of emiStruct) :
private EMI emiStruct;
private IntPtr emiIntPtr;
emiIntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(emiStruct));
Marshal.StructureToPtr(emiStruct, emiIntPtr, false);
EMIStruct.Error result = emi_init(emiIntPtr, hostname, portNumber, password, shortNumber, windowSize, throughput);
Marshal.PtrToStructure(emiIntPtr, emiStruct);
The last line (PtrToStructure) causes an exception "Attempted to read or write protected memory. This is often an indication that other memory is corrupt".
Also, I can see a debug output:
A first chance exception of type 'System.AccessViolationException' occurred in mscorlib.dll
First-chance exception at 0x7c970441 in XXXXX.exe: 0xC0000005: Access violation reading location 0xc3fffff8.
First-chance exception at 0x7c970441 in XXXXX.exe: 0xC0000005: Access violation reading location 0x01fffff7.
First-chance exception at 0x7c970441 in XXXXX.exe: 0xC0000005: Access violation reading location 0x00001f1d.
I assume the problem is somewhere in allocation of memory for the pointer emiIntPtr. Althought, when I run the code, and there is a problem with connecting to the server (e.g. server not found), the followed marshalling to the Struct emiStruct is done correctly (no exception). The problem only occurs when the connection is succesfully established and server send a respond.
Also, I wrote a C++ sample app using the same DLL library I'm trying to use in .NET, and this application (when I compile it) runs just fine - it means, the C++ DLL should be ok and not causing crashing.
Furthermore, I've found some hints to check/uncheck several properties for the project compilator (using JIT, compile it for x86 cpu, etc.), unfortunately, none of this helped.
Do you have any suggestion where the problem might be or how to do a correct IntPtr inicialization in .NET and mapping between IntPtr and Struct?
Thanks all for your replies:
Here I'm adding the C++ header of the emi_init func:
FUNC( init)( EMI* emi, /* out */
const char* hostname, /* in */
unsigned short port, /* in */
const char* password, /* in */
const char* origin_addr, /* in */
int window_sz, /* in */
int throughput); /* in */
And here is the C# emi_init declaration (I've removed the "ref" attribute for emiPtr as was suggested):
[System.Runtime.InteropServices.DllImport("emi.dll", EntryPoint = "_emi_init")]
public static extern EMIStruct.Error emi_init(
System.IntPtr emiPtr,
[System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string hostname,
ushort port,
[System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string password,
[System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string origin_addr,
int window_sz, int throughput);
However, still getting the same exception.
You are using Marshal.PtrToStructure incorrectly.
The second argument requires a type, iow typeof(EMI).
The return value contains the resulting struct.
So the solution should be:
var s = (EMI) Marshal.PtrToStructure(emiIntPtr, typeof(EMI));
My guess is that you have declared the first parameter incorrectly in the C#. You have declared it as ref IntPtr which is equivalent to EMI** in C++. But I bet the C++ declaration, which you unfortunately did not include, reads EMI*. So simply remove the ref and all should be well.
I expect that emi_init does not read from the EMI parameter, i.e. it has out semantics. In which case you don't need the StructureToPtr call before you call emi_init.

Memory AccessViolationException Error Calling DLL From C#

I'm encountering a strange memory read/write error while calling a compiled DLL from C#. I use DllImport to get a handle to the function we need, which writes a return value to a parametric pointer to an int (i.e., int* out). This function is called multiple times within a thread, and runs successfully over the execution life of the first thread. However, if one launches another thread after the first has completed, the call to the external dll throws an AccessViolationException. Since the multiple calls from the first thread execute successfully, I'm thinking this is somehow related to the first thread not releasing the pointers to the relevant integer parameters(?). If so, how can I explicitly release that memory? Or, perhaps someone has a different insight into what might be going on here? Thank you very much.
EDIT: Danny has requested more specifics, and I'm happy to oblige. Here is where the external routine is invoked:
int success = -1;
unsafe
{
int res = 0;
int* res_ptr = &res;
int len = cmd.ToCharArray().Length;
int* len_ptr = &len;
CmdInterpreter(ref cmd, len_ptr, res_ptr);
success = *res_ptr;
}
Where CmdInterpreter is defined as:
[DllImport("brugs.dll", EntryPoint="CmdInterpreter",
ExactSpelling=false, CallingConvention = CallingConvention.StdCall)]
public static unsafe extern void CmdInterpreter(ref string cmd, int *len, int *res);
Please let me know if there is any additional info that would be helpful. Thank you!
Given that the problem only occurs when multiple threads are involved, it may be that the command interpreter DLL is using some sort of thread-local storage and doing it incorrectly. It could also have to do with the COM initialization state of the second thread (the one that generates the error).
It would be interesting to know what happens if you launch your new thread and have it call into the DLL before making any calls into the DLL on your first/main thread. If it works, that might support the thread-local storage theory. If it fails, that would support the COM state theory.
It may be the [DllImport]. If you post the [DllImport] signature, and the DLL's ptototype, maybe we can spot a problem.
I read that the Managed, Native, and COM Interop Team released the PInvoke Interop Assistant on CodePlex. http://www.codeplex.com/clrinterop/Release/ProjectReleases.aspx?ReleaseId=14120

Categories

Resources