まず、質問: CLR 仕様は、同じプロセス内の複数のアプリ ドメインで実行されるコードが同じアドレス空間を共有することを保証しますか? 「アドレス空間を共有する」とは、アプリ ドメインの 1 つに割り当てられたメモリへのポインターが、同じプロセス内でホストされているすべてのアプリ ドメインで読み書きできることを意味します。
質問を説明する次の自己完結型の例を検討してください。プログラムWorker
は、別のアプリ ドメインにオブジェクトを割り当てます。はWorker
、10,000 個の整数用にメモリ ブロックを割り当て、データで埋めます。次に、プログラムはアプリ ドメインの境界を越えて呼び出し、割り当てられたブロックへのポインターを取得し、10,000 個のアイテムをすべて読み取れることを確認します。
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
);
}
}
}
}
}
これを何度も実行しましたが、毎回機能しました。直感的にはうまくいくはずです。結局のところ、アプリ ドメインは単一のプロセス内にあるため、同じ仮想アドレス空間を共有する必要があります。ただし、これは、Microsoft がいつでも削除できる機能の悪用のように感じます. このトリックの正当性を確認または否定する CLR の仕様に何かありますか?
なぜ私がこのような奇妙な質問をしているのか不思議に思っているかもしれませんが、空間と時間の両方で最小限のオーバーヘッドで、アプリケーション ドメインの境界を越えて大量の (ギガバイト単位の) データを渡す方法を探しています。その正当性を証明できれば、これは私の理想的な解決策です。