FIO09-C. システム間でのバイナリデータ転送に注意する
仕様の異なる複数のシステム間で関数 fread() と fwrite() を使用する場合は、可搬性が問題になる。特に、配列や構造体などの集成体型はいうまでもなく、整数などのスカラデータ型の読み書きも、データの表現や値が維持される保証はない。処理系ごとに、構造体のパディング、浮動小数点モデル、バイトあたりのビット数、ビッグエンディアンかリトルエンディアンかの区別などの属性が異なり、バイナリデータ形式の互換性が失われる可能性がある。
違反コード
以下のコード例は、ファイルストリームからデータ構造体にデータを読み取っている。
struct myData {
char c;
long l;
};
/* ... */
FILE *file;
struct myData data;
/* ファイルの初期化 */
if (fread(&data, sizeof(struct myData), 1, file) < sizeof(struct myData)) {
/* エラー処理 */
}
しかし、このコードは myData のレイアウトに関して仮定をしている。レイアウトはプラットフォームごとに異なる可能性がある。
適合コード
最適な解決法は、テキスト表現、またはデータの完全性を保証する特殊なライブラリを使用することである。
char c;
long l;
};
/* ... */
FILE *file;
struct myData data;
char buf[25];
char *end_ptr;
/* ファイルの初期化 */
if (fgets(buf, 1, file) == NULL) {
/* エラー処理 */
}
data.c = buf[0];
if (fgets(buf, sizeof(buf), file) == NULL) {
/* エラー処理 */
}
data.l = strtol(buf, &end_ptr, 10);
if ((ERANGE == errno)
|| (end_ptr == buf)
|| ('\n' != *end_ptr && '\0' != *end_ptr)) {
/* エラー処理 */
}
リスク評価
想定している形式とは異なる形式のバイナリデータを読み取ると、意図しないプログラム動作が引き起こされることがある。
| レコメンデーション | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
|---|---|---|---|---|---|
| FIO09-C | 中 | 中 | 高 | P4 | L3 |
自動検出
Compass/ROSE は違反コードが示すように、fread() に渡された struct へのポインタを識別することで、このレコメンデーションに違反している可能性がある部分を警告することができる。
参考情報
- [Summit 95], 20.5 on C-FAQ
翻訳元
これは以下のページを翻訳したものです。
FIO09-C. Be careful with binary data when transferring data across systems
