0

The string binding is invalid. This is what happens when I try to shut down a fairly complex application that consists of a C# EXE using a C++/CLI DLL than in turn references several C++ native static libraries and DLLs. (I'm using VS2013 and Boost 1.55.)

The problem occurs because _atexit (on DLL termination) is trying to call _t2m@???__Fep@?1???$get_static_exception_object@Ubad_exception_@exception_detail@boost@@@exception_detail@boost@@YA?AVexception_ptr@1@XZ@YAXXZ@?A0x8b93c95f@@YAXXZ, which is a native-to-managed thunk, and the CLR has presumably already been shut down by that point.

My main question is why a managed thunk is being registered in a native termination handler, since by definition that can't work. A related question is why a managed thunk is being generated for this type at all, since as far as I can tell every single #include of anything that could reference this type is either in a non-/clr-compiled file, or in a #pragma unmanaged block in a /clr-compiled file, so there shouldn't be any managed versions of it at all. (The help for #pragma managed says that it's the point of definition that defines whether templates are managed or not, not the point of instantiation.)

Perhaps I'm wrong about this, but I've always assumed that when #includeing the header file for native types (implemented in a non-/clr file) in a /clr file, it should be wrapped in an unmanaged block to prevent ODR problems.

A question (that I remember reading here but can't now find a link to) suggests that the solution is to remove all the pragmas and just let the compiler figure it out. However doing that results in Managed Debugging Assistant 'LoaderLock' has detected a problem on startup. (The call stack just points to the C# code that causes the C++/CLI DLL to be loaded, which is not entirely helpful.)

This question suggests that there's a compiler bug regarding template instantiation. Given that get_static_exception_object is a template, this seems plausible, but I'm not sure how to work around it.

Although another function that is similarly registered incorrectly is _t2m@???__FstrMgr@?1??GetInstance@CAtlStringMgr@ATL@@SAPAUIAtlStringMgr@2@XZ@YAXXZ@@YAXXZ, which is not a template, so that might be a red herring.

(I've tried reproducing the problem in a smaller example, but haven't been able to do so yet. Clearly there's some trigger I'm unaware of.)

Community
  • 1
  • 1
Miral
  • 12,637
  • 4
  • 53
  • 93
  • Templates are troublesome, they are expanded wherever they are used. So whether or not /clr or #pragma unmanaged is in effect at the #include does not play a role. The LoaderLock MDA has a knack for false warnings. You know the CLR is already loaded so flip the ignore bit and just turn the warning off. – Hans Passant Mar 01 '16 at 10:48
  • @HansPassant Except a direct quote from [the horse's mouth](https://msdn.microsoft.com/en-us/library/0adb9zxe(v=vs.120).aspx) says that *When a template function is instantiated, the pragma state at the time of definition for the template determines if it is managed or unmanaged.* ie. it's the state at the time of the include that should matter, not whenever the compiler chooses to instantiate it. Besides, the final one mentioned isn't even a template, just a static variable inside a regular method inside an unmanaged block. – Miral Mar 01 '16 at 22:45
  • It is not how it works, code generation is decided at function scope. Either a function is entirely MSIL or it is entirely machine code, it cannot be a mix. – Hans Passant Mar 01 '16 at 23:15
  • Right, but that doesn't conflict with anything I (or they) said, and still doesn't explain why it's generating MSIL or thunks at all. – Miral Mar 01 '16 at 23:17
  • Also, FWIW, if I try to ignore the LoaderLock MDA then it kills the process with exception 0xE0434352. So it's not that simple. – Miral Mar 01 '16 at 23:22
  • Hmm, there is a lot you are not telling us. You'll have to work on a minimum repro of this issue. If not for your own benefit to figure out what is going wrong then definitely to get an answer here. – Hans Passant Mar 01 '16 at 23:30
  • I know this thread is old but does anyone knows the flag that outputs the list of stack variables that shows if templates are compiled as managed or unmanaged. I had worked on a problem like this before and there was one templated variable that had been using the managed implementation when it should have used unmanaged and the way I figured it out was by generating this file at compile time and just going through each variable to make sure that it was using the correct implementation. Oh and the solution was to use #pragma unmanaged/managed in combination with pragma push/pop. – BoldAsLove Jan 22 '18 at 19:16
  • Edit to above: I believe it was a MAP file i generated that showed information on if a template was going to use the CLR runtime (i think unmanaged stack variables started with an underscore and managed didn't). I did this and found the templated variable that was using the CLR runtime dequeue when it shouldn't have been. The solution was to use #pragma unmanaged/managed in combination with pragma push/pop. – BoldAsLove Jan 22 '18 at 19:28

0 Answers0