CとC++のコードはいたるところで未定義動作に満ちている
CとC++言語において未定義動作(UB)が非常に広範囲に存在し、単なるメモリ安全性の問題を超えていることが指摘されている。ポインタの配置、型キャスト、関数呼び出しセマンティクスなど、多くの微妙なカテゴリーで未定義動作が発生する可能性があるとされる。
このテーマに関する記事によれば、C23標準には「未定義」という単語が283回出現し、正しいCまたはC++コードを書くことは極めて難しいとされている。著者はOpenBSDプロジェクトにバウンダリー外への書き込みバグの修正パッチを送付した。
未定義動作の具体例
未定義動作は、二重解放、使用後の参照、オブジェクト境界外へのアクセス、未初期化メモリへのアクセスなど多岐にわたる。ポインタ配置の不正も未定義動作である。C23標準セクション6.3.2.3では、正しく配置されていないオブジェクトへのアクセスが未定義動作と規定されている。
アーキテクチャによって動作が異なることも問題である。Linux Alphaでは、配置されていないアクセスがカーネルトラップを引き起こし、ソフトウェアが意図した動作をエミュレートする場合がある。SPARCではSIGBUSが発生する。一方、x86/amd64では配置されていないアクセスは問題を起こさないと考えられている。
型変換と関数呼び出しの落とし穴
C23標準セクション6.3.1.4では「有限値の実数浮動小数点型が整数型に変換される場合、積分部の値が整数型で表現できないとき、動作は未定義である」と規定されている。execlでNULLの代わりに(char*)NULLを使用しない場合も未定義動作となる。
NULL ポインタについても注意が必要である。C標準ではNULLポインタが機械アドレスのゼロを指すことは規定されていない。また、printfで%ldの代わりに%lldを使用するといった形式指定子の誤りは未定義動作を引き起こす。
著者による評価
著者は30年間、日々CおよびC++を書いてきた経験から、著者は「世界で最も優れたCプログラマーの手で書かれた6行のコードがあれば、その中から未定義動作を引き起こすのに十分な問題を見つけ出すことができる」と述べている。また、OpenBSDプロジェクトは30年以上の活動を続けてきたにもかかわらず、すべての未定義動作の問題を発見していないという事実は、修正の難しさを示唆している。
この記事は元記事の事実のみに基づいて自動生成されました。
筆者の見立て
- 正しいCまたはC++コードを書くことは不可能に近いと論じている。
- C++は有用であったが、1985年(C++の創成年)や1972年(C の創成年)の環境は現在の環境とは異なるとの解釈を示唆している。
- LLM(大規模言語モデル)の監督なしに2026年にC/C++を書くことはSOX違反であり無責任と見なされるべきと主張している。
- OpenBSDのような専門家でさえ問題を見つけられないのであれば、一般のプログラマーに成功の可能性があるのかと疑問を呈している。
- LLMはC コード内の未定義動作を発見する能力において人間より優れていると考えている。
- 専門家による検証が必要であるが、専門家は他の業務に忙しく対応できない可能性を示唆している。
出典
blog.habets.se 「Everything in C is undefined behavior」 https://blog.habets.se/2026/05/Everything-in-C-is-undefined-behavior.html (C23標準、OpenBSDプロジェクトによる)