Linux 7.2 が strncpy API を削除

Linux 7.2 は公式に Linux カーネルから strncpy API を削除しました。これは、残っていた内部利用者をすべて排除するために約 362 件のコミットを要した、6 年にわたる移行作業の完了を意味します。

strncpy が削除された理由

strncpy 関数は、カーネル内でバグとパフォーマンス低下の永続的な原因と見なされていました。その主な欠点は次の 2 点です。

  1. 直感に反するセマンティクス: NUL 終端に関する動作が誤解されやすく、メモリ安全性の問題を引き起こす可能性があります。具体的には、ソース文字列が指定サイズ以上の長さである場合、strncpy は宛先文字列を NUL 終端しません。
  2. パフォーマンスオーバーヘッド: ソース文字列が指定サイズ未満の場合、宛先バッファを余分にゼロ埋めするため、CPU サイクルが無駄になります。

ベテラン C 開発者である Walter Bright が指摘したように、コードベースに strncpy が存在することは、コードレビュー時に潜在的なバグの主要な指標となります。

Linux カーネルコードでの推奨置換

strncpy はさまざまな(しばしば相反する)目的で使用されていたため、Linux カーネルはより明示的な関数群に置き換えました。開発者はメモリ操作の具体的要件に応じて置換関数を選択する必要があります。

  • strscpy(): NUL 終端が必要な宛先に使用します。
  • strscpy_pad(): NUL 終端が必要で、かつゼロパディングが求められる宛先に使用します。
  • strtomem_pad(): NUL 終端されない固定幅フィールドに使用します。この関数は C 文字列を固定幅レガシーメモリフィールドに変換することを明示的に示すために設計され、sizeof(dest) に関連するバグを回避するために __nonstring 属性を利用します。
  • memcpy_and_pad(): 明示的なパディングが必要な境界付きコピーに使用します。
  • memcpy(): 長さが既に分かっているメモリコピーに使用します。

エンジニアリングの背景とコミュニティの洞察

長期的なシステムエンジニアリングの取り組み

strncpy の削除は、コミュニティから「システムエンジニアリングの退屈な磨き作業」の好例と見なされています。新機能の追加とは異なり、レガシー API を大規模コードベースから除去するには、安定性を保ちつつ機能を維持するための計画的で数年にわたるアプローチが必要です。

API の歴史的背景

業界のベテランは、strncpy が当初は初期 UNIX の非常に特化したユースケース向けに設計されたことを指摘します。具体的には、2 バイトの inode 番号と 14 バイトのゼロパディングされた非終端名フィールドからなるディレクトリエントリにファイル名をコピーするためのものでした。これを汎用的な文字列コピー関数として使用することは、何十年も続いた根本的な誤用でした。

C 言語への広範な批判

この削除に関する議論は、C 言語の文字列取り扱いに対する継続的な不満を浮き彫りにしています。コミュニティメンバーは、ファットポインタやスライス、文字列ビューといったネイティブな文字列型が存在しないため、開発者がこれらの複雑でエラーが起きやすい手動メモリ管理関数に頼らざるを得ないと指摘しています。一部の貢献者は、パスカル風文字列や std::string(C++)に似た「ポインタと長さを保持する構造体」の採用が、こうした問題を根本的に防げたのではないかと提案しています。

Sources