同様の状況に遭遇した他の人にとって、ここでの問題は、インラインアセンブリにも、それが呼び出されていた方法にもありませんでした。それは、プログラムのクラス/構造体にありました。私が犯罪者であると信じていたクラスは問題ではありませんでした-そのインスタンスを保持する別のクラスがあり、その外側のクラスの他のメンバーのために、内側のクラスは単語の境界に整列していませんでした。これは私が経験していた「バスエラー」を引き起こしていました。クラスが他のコードで宣言されていなかったため、これまでに遭遇したことはありませんでした__attribute__((packed))
が、それらは私の実装に含まれています。
タイプ属性を与える-GNUコンパイラコレクション(GCC)を使用して、読み取りが実際に私にとっての答えを引き起こしたものでした。メモリアライメントに影響を与える2つの特定の属性(したがって、私が使用しているようなインラインアセンブリ)はとpacked
ですaligned
。
前述のリンクから取得:
整列(整列)
この属性は、指定されたタイプの変数の最小アライメント(バイト単位)を指定します。たとえば、宣言は次のとおりです。
struct S { short f[3]; } __attribute__ ((aligned (8)));
typedef int more_aligned_int __attribute__ ((aligned (8)));
struct S
タイプがmore_aligned_intである各変数が、少なくとも8バイト境界で割り当てられ、整列されるように、コンパイラーに(可能な限り)強制します。SPARCでは、型のすべての変数struct S
を8バイト境界に揃えることで、コンパイラは型の変数を別の変数にコピーするときにldd
and (ダブルワードのロードおよびストア)命令を使用できるため、実行時の効率が向上します。std
struct S
ISO C規格では、任意のstruct
またはタイプのアラインメントは、または問題union
のすべてのメンバーのアラインメントの最小公倍数の少なくとも完全な倍数である必要があることに注意してください。これは、そのようなタイプのメンバーのいずれかに属性を付加することで、またはタイプの配置を効果的に調整できることを意味しますが、上記の例に示されている表記法は、コンパイラーを要求するためのより明白で直感的で読みやすい方法です。またはタイプ全体の配置を調整します。struct
union
struct
union
aligned
struct
union
struct
前の例のように、コンパイラーが特定のタイプまたはタイプに使用するアライメント(バイト単位)を明示的に指定できますunion
。または、アラインメントファクターを省略して、コンパイルするターゲットマシンの最大の有用なアラインメントにタイプをアラインメントするようコンパイラーに要求することもできます。たとえば、次のように書くことができます。
struct S { short f[3]; } __attribute__ ((aligned));
アラインされた属性指定でアラインメント係数を省略すると、コンパイラーは、タイプのアラインメントを、コンパイル対象のターゲットマシン上の任意のデータ型でこれまでに使用された最大のアラインメントに自動的に設定します。これを行うと、多くの場合、コピー操作がより効率的になります。コンパイラは、この方法で整列した型を持つ変数との間でコピーを実行するときに、メモリの最大のチャンクをコピーする命令を使用できるためです。
上記の例では、それぞれのサイズshort
が2バイトの場合、タイプ全体のサイズstruct S
は6バイトです。それ以上の2の最小の累乗は8であるため、コンパイラーはstruct S
タイプ全体のアラインメントを8バイトに設定します。
特定のタイプの時間効率の良いアラインメントを選択してから、そのタイプの個々のスタンドアロンオブジェクトのみを宣言するようコンパイラーに要求できますが、時間効率の高いアラインメントを選択するコンパイラーの機能は、主に次のことを計画している場合にのみ役立ちます。関連する(効率的に整列された)型を持つ変数の配列を作成します。効率的に整列された型の変数の配列を宣言または使用する場合、プログラムは、関連する型へのポインター、およびコンパイラーが行うコードに対して、ポインター演算(または同じことになる添え字)も実行する可能性があります。これらのポインタの算術演算の生成は、他の型よりも効率的に整列された型の方が効率的であることがよくあります。
aligned属性は、alignmentを増やすことしかできません。ただし、packedを指定することで減らすことができます。下記参照。
整列された属性の有効性は、リンカーに固有の制限によって制限される場合があることに注意してください。多くのシステムでは、リンカは変数を特定の最大整列まで整列させることしかできません。(一部のリンカーでは、サポートされる最大アラインメントが非常に小さい場合があります。)リンカーが変数を最大8バイトのアラインメントまでしかアラインできない場合、それでもで指定するaligned(16)
と__attribute__
8バイトのアラインメントしか提供されません。詳細については、リンカのドキュメントを参照してください。
。
パック
この属性は、定義struct
またはunion
型定義に付加され、必要なメモリを最小限に抑えるために、構造体または共用体の各メンバー(ゼロ幅ビットフィールドを除く)が配置されることを指定します。定義に添付するenum
と、最小の積分型を使用する必要があることを示します。
この属性をstruct
およびunion
typesに指定することは、各構造体または共用体メンバーにpacked属性を指定することと同じです。-fshort-enums
行にフラグを指定することは、すべての定義に属性を指定することと同じですpacked
。enum
次の例では、struct my_packed_struct
のメンバーは密にパックされていますが、そのs
メンバーの内部レイアウトはパックされていません。そのためには、メンバーもパックstruct my_unpacked_struct
する必要があります。
struct my_unpacked_struct
{
char c;
int i;
};
struct __attribute__ ((__packed__)) my_packed_struct
{
char c;
int i;
struct my_unpacked_struct s;
};
この属性は、列挙型、構造体、または共用体も定義していない、、またはenum
のstruct
定義でのみ指定できます。union
typedef
私が経験した問題は、特にの使用によるものでしpacked
た。aligned
構造体とクラスに属性を追加しようとしましたが、エラーが解決しませんでした。属性を削除するだけpacked
で問題は解決しました。今のところ、私はaligned
それらに属性を残し、単に単語の境界に配置されているために、上記のようにコードの効率に改善が見られるかどうかをテストしています。アプリケーションはこれらの構造体の配列を利用するため、パフォーマンスが向上する可能性がありますが、コードのプロファイリングのみが確実になります。