Initializing code

A common question is how to initialize code before it is called. In the unmanaged world, this is done with a DLL_PROCESS_ATTACH notification to your DllMain routine. Managed C++ can actually use this same technique. However, it has all the usual restrictions and problems related to the operating system’s loader lock. This approach is not…


Inheriting from MarshalByRefObject

Developers often wonder why they are forced to derive from MarshalByRefObject or EnterpriseServices.ServicedComponent. It would be so much more convenient if they could add a CustomAttribute to their class or use a marker interface to declare that they want to be marshaled by reference or they want serviced behavior. The reason has to do with…


Managed objects and COM

All managed objects other than those derived from ServicedComponent, when exposed to COM, behave as if they have aggregated the free threaded marshaler (FTM). In other words, they can be called on any thread without any cross-apartment marshaling. Although managed objects act as if they aggregate the FTM, they don’t actually aggregate it because that…


Surprising ‘protected’ behavior

There’s a subtle but important difference between protected access in unmanaged C++ and protected access (i.e. family) in the CLR. The difference is due to the CLR’s ability to build security guarantees on top of type safety. Imagine you had a bifurcated hierarchy: Class A { protected M } /                      Class G : A         Class X : A There is no relationship between X and G, except…


What is SEHException?

One way you get this exception is if unmanaged code does an OS RaiseException() or causes a fault.  If that exception is propagated up the stack to managed code, we will try to map it to a managed exception.  For example, STATUS_NO_MEMORY maps to OutOfMemoryException and STATUS_ACCESS_VIOLATION maps to NullReferenceException.   For all the exception codes that don’t have a predefined…


Size of a managed object

We don’t expose the managed size of objects because we want to reserve the ability to change the way we lay these things out. For example, on some systems we might align and pack differently. For this to happen, you need to specify tdAutoLayout for the layout mask of your ValueType or Class. If you…


DLL exports

People often ask how they can expose traditional DLL exports from managed assemblies. Managed C++ makes it very easy to export functions. And you could use tricks like ILDASM / ILASM to inject DLL exports into managed assemblies built with other languages like C#. However, there is a fundamental mismatch between the process-wide notion of…


Hyper threading

If the operating system schedules multiple threads against a hyper-threaded CPU, the CLR automatically takes advantage of this. This is certainly the case for new versions of the OS like Windows Server 2003. Also, the CLR did work to properly spin on a hyper threaded system. If you are writing your own spinlocks in managed…


Turning off the garbage collector

It is not generally possible to turn off garbage collection. However, the garbage collector won’t run unless “provoked.” Garbage collection is triggered by: Allocation Explicit calls by the application to System.GC.Collect Explicit calls by the application to services that implicitly trigger a GC. For example, unloading an AppDomain will trigger at least one full GC….


Error C0020001

#define BOOTUP_EXCEPTION_COMPLUS 0xC0020001 You may see an exception with this code, or an HRESULT of this value, when trying to call into managed code. This can happen if you call in before the runtime has finished initializing, or after the runtime has started shutting down. Sometimes it’s obvious how you run into this situation. For…