こんな標準ライブラリは嫌だ!

高木です。おはようございます。

これまで使ったことがない処理系に関わることになった場合、可能であれば標準ライブラリの実装を確認するようにしています。
Cの場合は標準ライブラリもそんなに大きくないので、ソースコードが提供されていれば、大体確認していますね。

そんなこともあって、これまで様々なCの標準ライブラリに遭遇してきました。
今回はそうした経験から、とくに印象深かったものを紹介したいと思います。

その処理系は、私が最初に関わる前に何度かバージョンアップを繰り返していたようです。
マイコン向けの処理系なので、特殊な拡張機能も多く、それらがバージョンアップによって互換性を失うことも少なくないようでした。

マイコンのプログラムでは、命令とデータをどこに配置するかが重要になってきます。
基本的に読み出し専用の命令はROMに配置すべきですし、読み書き可能なデータはRAMに配置すべきです。
データのうち読み出し専用のものは、スペース的な問題がなければRAMに配置することもできますが、ROMに配置するのが普通です。
ただし、ROMよりRAMのほうが高速にアクセスできるようなプラットフォームでは、命令もデータもRAMに配置することもあります。

今回紹介する(実名は出しませんが)処理系は、昔のバージョンは#pragma指令によってROMに配置するかRAMに配置するかを明示的に指定していました。
ところが、その後のバージョンアップによって、const修飾子を付加した静的記憶域期間を持つオブジェクトはデフォルトでROMに配置されるようになったようです。
それと同時に、以前あった#pragma指令は廃止されたのです。

ここで悲劇が起きます。

ヘッダで宣言されるis系関数は、典型的には表引き方式で実装されています。
今回の悲劇の処理系も例にもれず、表引き用の256バイトの配列が定義されていました。

その表引き用の配列は、以前の仕様にあわせて#pragma指令でROMに配置されるように指定されていました。
残念なことに、その#pragma指令を過信してか、const修飾子が付けられていなかったのです。

そして、バージョンアップによって悲劇のときは訪れます。
ROMに配置するための#pragma指令は廃止され、const修飾子も付いていない表引き用の配列は、なけなしのRAMを占有するようになってしまいました。

その処理系は16ビットマイコン用のものであり、当初は数kバイトから十数kバイト程度のRAMを内蔵していたように思います。
ところが、そのマイコンのローエンド版が登場し、標準ライブラリが流用されたのです。

ローエンドのマイコンだけに、RAMのサイズは256バイト以下のものが主流でした。
256バイトに満たないRAMしか持たないマイコンなのに、256バイトの表引き用配列がRAMを占有してしまうのです。
これを悲劇といわずして、何を悲劇と呼べばいいのでしょうか?

私はそうした標準ライブラリの実装を見て以来、少なくともその処理系に関しては、標準ライブラリに含まれるどの関数も手放しには信用しなくなりました。
Cの標準ライブラリ程度であれば、時間が許せば自分で実装しなおすほうがずっとまともなものができそうですしね。