私はstackoverflowに新しいです。私はC#構造体とそのレイアウトに関する質問があります。 構造体へのポインタのFieldOffsetを固定バイト配列と同じ値に設定
はのは、以下の構造体を想定してみましょう:[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct Link
{
// some primitive data (2 integers for example)
}
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public unsafe struct Node
{
[FieldOffset(0)]
public int LinkCount;
[FieldOffset(4)]
public Link* Links;
[FieldOffset(4)]
private fixed byte _linksData[10 * sizeof(Link)];
}
その理由は、私はIO-パフォーマンスのためのblittable型タイプを必要とするということです。 私は数GBの大きさの非常に大きな(ノード当たり最大10のリンク)グラフに対処しなければなりません。 グラフはノード構造体の配列として表されます。 上記のような設定では、グラフファイルからバイトポインタ(もちろんバイトバッファを指しています)に100 MBを読み込み、それをNode *型のポインタにキャストすることを期待していました非常に良好な性能をもたらす。 最初に私のNode-structには、Link(Link0、...、Link10)型の別々の変数が10個しかありませんでした。しかし、コンパイル時にこれを設定可能にして、上記のNode-structにつなげるとよいでしょう。
私は望んでいたのは、リンクは同じフィールド位置を持っているので、_linksDataと同じメモリ位置を指しているだけです。 しかし、実際にはLinksポインタは常にnullポインタです。
私の質問は: リンクが_linksDataと同じメモリ位置を指す方法はありますか、別の構造体に埋め込まれた構造体の固定サイズの配列を持つ別の方法がありますか?事前にすべての答えを
おかげ - マルクス
はベンフォークトの記事を読んだ後、私はクラスに構造体を変更する必要なく、類似した何かをしようと試みました。以下は、どのように私のために働いています:
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public unsafe struct Node
{
[FieldOffset(0)]
public int LinkCount;
[FieldOffset(4)]
private fixed byte _linksData[10 * sizeof(Link)];
public Link* GetLinks()
{
fixed(byte* pLinksData = _linksData)
{
return (Link*)pLinksData;
}
}
}
最後のスニペットは深刻な問題を引き起こします。ポインタは固定ブロック内でのみ有効です。あなたが出てくると、返されたポインタは構造体が格納されているどこにでもぶら下がります。そして.NETの中には良いところがありません。良いところはスタックもgcヒープもありません。構造体を非管理メモリに明示的に整列化しない限り。 –
@ハンス:私は、Markusはオブジェクトがなくなった後にポインタを使用しないほどスマートだと思います。これはスタック変数にとって十分です。しかし、クラスインスタンスのメンバーにとって、実際には問題があり、私もこれについて言及しました。 –
@Hans Uhhh - 本当に感謝しました。しかし、私の実際のプロジェクトでは、私はとにかくベンのような彼の例で示された1つのリンクだけを返します。 – Markus