問題のデバッグ中に、次の問題が発生しました。(マイナーなコードエラーは無視してください。コードは説明のためだけのものです。)
次の構造体が定義されています。
typedef struct box_t {
uint32_t x;
uint16_t y;
} box_t;
この構造体のインスタンスは、関数から関数に値で渡されます(明らかに単純化されています)。
void fun_a(box_t b)
{
... use b ...
}
void fun_b(box_t bb)
{
// pass bb by value
int err = funa(bb);
}
void fun_c(void)
{
box_t real_b;
box_t some_b[10];
...
... use real_b and some_b[] ...
...
funb(real_b);
funb(some_b[3]);
...
box_t copy_b = some_b[5];
...
}
場合によっては、box_tの2つのインスタンスが次のように比較されます。
memcmp(bm, bn, sizeof(box_t));
いくつかのネストされた呼び出し内で、box_targのバイトは次のようなものを使用してダンプされました。
char *p = (char*) &a_box_t_arg;
for (i=0; i < sizeof(box_t); i++) {
printf(" %02X", *p & 0xFF);
p++;
}
printf("\n");
sizeof(box_t)は8です。2つのパッドバイトがあります(uint16_tの後にあるものとして検出されます)。ダンプは、構造体のフィールドが等しいことを示しましたが、パッドバイトは等しくありませんでした。これにより、memcmpが失敗しました(当然のことながら)。
興味深い部分は、「破損した」パッド値がどこから来たのかを発見することでした。逆方向に追跡した後、box_tインスタンスの一部がローカル変数として宣言され、次のように初期化されていることがわかりました。
box_t b;
b.x = 1;
b.y = 2;
上記は、「ガベージ」(bに割り当てられたスタックスペースにあったもの)を含むように見えるパッドバイトを初期化しません(表示されます)。ほとんどの場合、初期化はを使用して行われましたmemset(b, 0, sizeof(box_t))
。
問題は、(1)構造体の代入または(2)値の受け渡しのいずれかによってbox_tのインスタンスを初期化すると、常にsizeof(box_t)のmemcpyと同等になるかどうかです。'実際のフィールド'の6バイトだけがコピーされる(そしてパッドバイトはコピーされない)というのはこれまでにありますか?
デバッグから、memcpy sizeof(box_t)と同等のものが常に実行されているように見えます。これを実際に指定するものはありますか(たとえば、標準で)?デバッグが進むにつれて、パッドバイトの処理に関して何が期待できるかを知ることは役に立ちます。
ありがとう!(Ubuntu LTS 10.464ビットでGCC4.4.3を使用)
ボーナスポイントの場合:
void f(void)
{
box_t ba;
box_t bb;
box_t bc;
sizeof()が8を示している間、3つのインスタンスは16バイト離れて割り当てられます。なぜ余分なスペースがあるのですか?