First, the question: do CLR specifications guarantee that the code executing in multiple app domains within the same process will share the same address space? By "sharing the address space" I mean that pointers to memory allocated in one of the app domains will be valid for reading and writing across all app domains hosted inside the same process.
Consider this self-contained example illustrating the question: the program allocates a Worker
object in a separate app domain. The Worker
allocates a memory block for 10,000 integers, and fills it in with data. The program then calls across the app domain boundary to obtain the pointer to the allocated block, and verifies that it can read every one of the 10,000 items.
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace crossapp {
public class Worker : MarshalByRefObject {
private readonly IntPtr myData;
public const int DataLength = 10000;
public Worker() {
Console.Error.WriteLine(
"Memory allocation happens in app domain '{0}'"
, Assembly.GetExecutingAssembly().FullName
);
myData = Marshal.AllocHGlobal(sizeof(int) * DataLength);
unsafe {
var ptr = (int*) myData.ToPointer();
for (var i = 0 ; i != DataLength ; i++) {
ptr[i] = 2*i + 1;
}
}
}
public IntPtr GetData() {
return myData;
}
}
class Program {
static void Main() {
var ad = AppDomain.CreateDomain("New domain");
var wrk = (Worker)ad.CreateInstanceAndUnwrap(
Assembly.GetExecutingAssembly().FullName
, "crossapp.Worker"
);
var data = wrk.GetData();
var badCount = 0;
unsafe {
var ptr = (int*)data.ToPointer();
for (var i = 0 ; i != Worker.DataLength ; i++) {
var expect = 2*i + 1;
if (ptr[i] != expect) {
Console.Error.WriteLine(
"Mismatch in position {0}: {1} != {2}"
, i, expect, ptr[i]
);
badCount++;
}
}
if (badCount == 0) {
Console.Error.WriteLine(
"All {0} items have matched."
, Worker.DataLength
);
} else {
Console.Error.WriteLine(
"Found {0} mismatches out of {1}."
, badCount
, Worker.DataLength
);
}
}
}
}
}
I ran this many times, and it worked every single time. Intuitively it should work: after all, app domains are within a single process, so they must share the same virtual address space. However, this feels like an exploit of a feature that Microsoft may take away at any time. Is there something in the specification of CLR that confirms or denies legitimacy of this trick?
In case you are wondering why I am asking such a strange question, I am looking for a way of passing large (in gigabytes) amounts of data across app domain boundary, with minimal overhead in both space and time. This would be my ideal solution if I could prove its legitimacy.
I have no direct answer for you. The existance of MarshalByRefObject might indicate that a common address space is used, but perhaps not.
You might also look into memory-mapped files