warning: padding struct to align ‘i2’
警告:i2′ を整列するため構造体に詰め物した
[-Wpadded]
■この記事の概要
この記事では、C言語でmemcmp
を使った構造体の比較に関する問題を解説しています。構造体内のパディング(詰め物)が比較に影響を及ぼし、予期しない動作を引き起こす可能性があります。具体例を挙げ、比較時の注意点や安全な手法について説明しています。
■境界調整のために穴が開く
構造体のメンバの割り付けはコンパイラ任せなので
各メンバがピッタリ隙間なく割り付けられるとは限りません。
境界調整のために穴が開く場合があり
穴に何が書かれているかは誰もわかりません。
■構造体パディングの例
#include <stdio.h>
#include <string.h>
#include <stdint.h>
struct hole {
uint32_t i1 ;
uint8_t c ;
// 3byteの穴
uint32_t i2 ;
} ;
//構造体をダンプする
static void memdmp(uint8_t *d1,uint8_t *d2,size_t size){
for(size_t i = 0 ; i < size ;i++){
if(d1[i] == d2[i]){
continue;
}
printf("d1[%2zd]=%2x d2[%2zd]=%2x\n",
i,d1[i],
i,d2[i]
);
}
}
//メンバの内容が同じ構造体を比較する
void cmp(void){
struct hole 自動変数 = {
.i1 = 0x12345678,
.c = 0xab,
.i2 = 0x87654321
};
static struct hole 静的変数 = {
.i1 = 0x12345678,
.c = 0xab,
.i2 = 0x87654321
};
int ret = memcmp(&自動変数,&静的変数,sizeof(自動変数)) ;
printf("memcmpの結果=%d\n",ret) ;
if(ret != 0){
memdmp((uint8_t *)&自動変数,(uint8_t *)&静的変数,sizeof(自動変数));
}
}
//自動変数領域をFFで汚す
void ff(void){
struct hole ff;
memset(&ff,0xFF,sizeof(ff));
}
int main(void){
ff(); //自動変数領域をFFで汚す
cmp();
}
構造体の詰め物(=穴=パディング)の内容は
未規定(=コンパイラ依存)なので、
このプログラムの7行目の【穴】に何が入っているのか
わかりません。
➡筆者環境下gcc最適化無しの実行結果
./a.out
memcmpの結果=12
d1[ 5]=ff d2[ 5]= 0
d1[ 6]=ff d2[ 6]= 0
d1[ 7]=ff d2[ 7]= 0
➡筆者環境下gcc最適化有りの実行結果
参考:
EXP04-C. 構造体を含むバイト単位の比較を行わない
https://www.jpcert.or.jp/sc-rules/c-exp04-c.html
C-FAQ 2.8: なぜ構造体を比較することはできないのか。
http://www.kouno.jp/home/c_faq/c2.html#8