メモリ管理(1)
• スタック
• 一番上に積む・一番上から取り出す
•ローカル変数用
• 管理は楽
• スコープがはっきりしてないと使えない
int x = 1;
int y = 2;
int z = 4;
int sum = x + y + z; 1 1
2
load 1 load 2
3
add
3
4
load 4
7
add
unsafeでも制限付き
• class (参照型)はアドレス取れない
•仮想メソッド テーブル(vtable)とか入ってるし
• 親クラス側のレイアウト変更の影響受けるし
class Class
{
public int x;
public int y;
}
var c = new Class();
fixed (void* p = &c) { } // error
fixed (void* p = &c.x) { } // OK
fixed (void* p = &c.y) { } // OK
ピン止め必須
• 値型のメンバーのアドレスは取れる
• オブジェクト自体のアドレスは取れ
ない
28.
unsafeでも制限付き
• struct (値型)はアドレス取れる
•ただし、メンバーが全部値型の時のみ†
• ↑「unmanaged型」と呼ぶ
struct UnmanagedStruct
{
public int x;
public int y;
}
var u = new UnmanagedStruct();
void* p1 = &u; // OK
void* p2 = &u.x; // OK
void* p3 = &u.y; // OK
メンバーが
全部値型
無制限にアドレス取れる
† 正確には、再帰的に全子要素が値型、かつ、型パラメーターも値型
29.
unsafeでも制限付き
• struct (値型)であっても制限付き
•メンバーに1つでも参照型を含むとダメ
• ↑「managed型」と呼ぶ
struct ManagedStruct
{
public int x;
public string y;
}
var u = new ManagedStruct();
void* p1 = &u; // error
void* p2 = &u.x; // OK
void* p3 = &u.y; // error
メンバーに
参照型が1つ
本体のアドレス取れない
値型のメンバーのところ
だけはアドレス取れる
メタデータとは
• 実行可能ファイル中には本来不要なデータ
• プログラムを作るためのデータ
•実行に必要なデータよりもメタ(高次)
var x = p.X;
var y = p.Y;
var z = p.Z;
var pp = (byte*)&p;
var x = *((int*)pp);
var y = *((int*)(pp + 4));
var z = *((int*)(pp + 8));
プロパティ名とか
単にプログラムを動かすだけなら
相対アドレスだけわかればいい
.NETでは、こういうメタデータを実行可能ファイルに残す
差分ダウンロード
※ Windowsストア アプリはこういう仕組み持ってる
アプリAライブラリX
ライブラリY
アプリAパッケージ version 1
version 1
アプリA ライブラリX
ライブラリY
アプリAパッケージ version 2
version 2
version 1 version 1
version 1 version 1
ライブラリX
差分
version 2
ダウンロード
アプリA ver.1
インストール機
バージョンアップ時
更新
ここだけ新しい
メモリ レイアウト
• この4とか8の意味
publicstruct Point
{
public int X;
public int Y;
public int Z;
}
Point
X
Y
Z
4バイト
8バイト
※レイアウトがどうなるかは環境依存
83.
メモリ レイアウト
• この4とか8の意味
publicstruct Point
{
public int X;
public int Y;
public int Z;
}
Point
X
Y
Z
4バイト
8バイト
※レイアウトがどうなるかは環境依存
ILの時点までは名前
で参照してる
ネイティブ コードは
レイアウトを見て
数値で参照してる
84.
数値でのフィールド参照
• C#で擬似的に書くと
static intGetVolume(Point p)
{
return p.X * p.Y * p.Z;
}
var pp = (byte*)&p;
var x = *((int*)pp);
var y = *((int*)(pp + 4));
var z = *((int*)(pp + 8));
return x * y * z;
4とか8とかの数値に
※これ、一応C#として有効なコード(unsafe)