2

私は次の構造体を持っています:

struct foo
{
   int  a;
   char b;
};

これはメモリに格納され、それへのポインタはアラインされていない可能性があります (奇数アドレス)。

それで、これは安全ですか?:

const struct foo a = *((struct foo*)char_ptr); 

ソース構造体の整数メンバーが奇数アドレスになる可能性があるため、心配しています。一部のシステムでは、奇数アドレスから (マルチバイト) 整数を読み取ると問題が発生します。

編集: の使用に関するトピック外のコメントを避けるために、コードからconsta を削除しました。const(const ポインターを非 const ポインターにキャストすることはありません。この場合でも、問題は発生しません)

さらに、問題のコンテキストについて: この種の構造は、プロトコル フレームの一部です。また、フレーム内の任意のオフセットにすることができます。実際のコードでは、構造体に__attribute__((packed))属性があります。しかし、それはおそらく答えを変えませんか?

とにかく、問題を解決するためにmemcopyand non-constを使用できました。aしかし、よりエレガントな方法のように見えるので(安全であれば)、割り当てを使用したいと思います。

4

3 に答える 3

2

データ構造のパディングを参照してください。ほとんどのシステムでは、構造体は整列され、内部メンバーアドレスはそれぞれのサイズで整列され、それ自体をmallocします。

メモリプールを手動で作成し、その中のいくつかのセクションを使用して構造体オブジェクトを格納する場合、コンパイラはアライメントを保証しませんが、malloc を使用して構造体オブジェクトを作成する場合、アライメントされたアドレスを提供することは一般にコンパイラの頭痛の種です。構造体要素間に必要な場合はパディングを使用します。

于 2012-12-05T12:22:44.627 に答える
1

いいえ、構造体に必要なアラインメントがポインターにあることがわかっていない限り、安全ではありません。

ポインターが必要な配置を持っていることを確認するいくつかの方法を次に示します。

  • ポインターは、char へのポインターに変換される前は、この構造体型へのポインターでした。
  • mallocポインターは、返されたアドレスがあらゆる用途に適切に割り当てられることを保証するメモリ割り当てルーチン ( など) の結果です(これmallocは保証します)。
  • ポインターは、目的の配置を維持する方法で上記のいずれかから計算されています。
  • C 実装でサポートされている場合は、ポインターを a に変換し、uintptr_tそのアラインメントをテストします。
  • C 実装 (特に OS とプロセッサ) では、構造内の型のオブジェクトへの境界整列されていないアクセスが許可されています。

ポインターが必要なアラインメントを持っているかどうかわからない場合は、変換されたポインターを介して構造体にアクセスしないでください。代わりに、新しい構造体を定義し、 を使用memcpyして文字へのポインターから新しい構造体にコピーすることができます。

于 2012-12-05T14:30:00.980 に答える
1

データへのポインターが必ずしもアライメントされていないソースからデータを取得する場合、できる唯一の安全な方法は memcpy であり、コンパイラーが「スマート」ではなく、位置合わせされていないポインターが実際にアライメントされているふりをすることを望みます。 memcpy は最適化できます (このバグを持つ古いバージョンの gcc がいくつかあり、memcpy と呼ばれないカスタム memcpy 関数を作成する必要があります)。アーキテクチャによっては、不適切にアラインされたアクセスを回避できますが、ほぼ確実に遅くなり、カーネル トラップを介してエミュレートされることもあります。

余談: これは通常、オペレーティング システムのネットワーク スタックの問題であり、イーサネット ヘッダーのサイズが奇数であるために IP ヘッダーが整列されず、ハードウェアに受信パケットの整列を誤らせる機能がない場合に発生します (一部の DMA エンジンは、 4 バイト境界上のデータ)、これにはヘッダー全体 (またはパケット全体) をソフトウェアでもう一度コピーする必要があります。

于 2012-12-05T12:35:17.227 に答える