Unicodeの落し穴 - 文字コードと文字列処理

宇宙の境界条件は、それが境界を持たないということだ。
スティーヴン・W・ホーキング 『ホーキング、宇宙を語る
Unicodeといえば、文字コードの一種。文字コードをあまり意識しない方でもほとんどの方は御存じでしょう。しかし、Unicodeというか文字コードに関して、いくつかありがちな誤解があり、それが原因でバグにはまることもあります。ということで、今回はUnicodeと文字コードの話です。

■文字コードと符号化方式

4798100307文字コードといった時によく、混同されるのが文字集合(character set)と符号化方式(encoding type)。文字集合はその名のとおり、文字の集合を定義したもので、日本語であれば JIS X 0208(第一、第ニ水準)をはじめ、JIS X 0212(補助漢字) 、 JIS X 0213(第三、第四水準)等があります。 それに対して、符号化方式とは、文字集合に含まれる各文字をどのようなコードに割り当てるのかというもの。 1つの文字集合JIS X 0208に対しても、ISO-2022-JPShift-JISEUC-JP等があります。この辺の話は、textファイルやソースコードの編集時や、Webページの閲覧時に問題になることが多いので馴染み深いですよね。
そして、問題のUnicodeですが、これは多言語を同時に扱うことを目的として開発された文字コード体系です。符号化方式は可変長の8ビットコードであるUTF-8、16ビットもしくは32ビットでエンコードするUTF-16等があります。

さて、ここまでで何が問題なのかというと、Unicodeを符号化方式を表すものと勘違いしている人がいることです。UTF-8とUTF-16はともに良く使用される符号化方式ですが、「Unicode文字列を処理する」といった場合に、どちらか一方でエンコードされていることを期待しているソースコードを書いてしまい、それがバグの原因になることがあります。

■ワイド文字列・マルチバイト文字列の文字列処理

プログラミングにおいて、文字コードが直接影響するのは文字列処理です。C言語でいれば、strcpy, strcmp, printf等など。C言語における文字列は、「NULL終端文字('\0')までのバイト列(char配列)」というのは、これは、ASCIIを始めとする1バイト文字列での話。ワイド文字列では、これが「ワイドNULL文字('\0\0' 2バイトの0)までのワイド文字列」となります。
これはつまり、ワイド文字列に対してstrcpy等の従来の文字列処理のライブラリが使えないということを意味しています。内部で、strcpy等を利用しているライブラリも同様です。ワイド文字列では、終端以外でも0が入ることがあるので、意図しないところで終端扱いされ、途中までしか文字列がコピーされないといったようなことが起こります。

Unicodeに関しては、UTF-8でエンコードされている間はNULL終端文字を期待する従来の文字列処理関数が使用できますが、これがUTF-16だとそうはいきません。よって、Unicode対応をUTF-8対応と思っていると、strcpyを使っているようなコードでも問題ないと判断してしまいそうですが、実はUTF-16への対応が必要だったという場合にバグを引き起こします。

■資産の流用と文字コード

Unicode自体はまだ発展途上とも言える技術ですが、徐々に使用範囲が拡がっています。よって、今まではUnicodeを扱わなかったようなライブラリでも、Unicode文字列を扱わなければならないケースがあるでしょう。その際には、文字コードにおける符号化方式の違い、ワイド文字列に対する互換性問題に対して、正しい認識を持って問題にあたることが必要でしょう。

【関連書籍】
Unicode標準入門 トニー・グラハム 乾和志
Cプログラミングの落とし穴 A.コーニグ
文字コード超研究 深沢 千尋
プログラミング言語C ANSI規格準拠 B.W.カーニハン D.M.リッチー
図解入門 よくわかる最新ファイル形式と文字コードの基本と仕組み―データ形式、ファイル構造、文字コード基礎講座

【関連リンク】
Unicode (Wilipedia)
文字コード (Wikipedia)
Manpage of PRINTF

大規模ファイルを扱うには - 2Gの壁とLSF仕様

誰もが自分自身の視野の限界を世界の限界だと思い込んでいる。
アーサー・ショーペンハウエル
32bitの符号付き整数の最大値は2G、符号無しなら4G。それ以上は表せません。そのため、いわゆる2Gの壁、4Gの壁と呼ばれるものがあります。代表的なものはファイルサイズ、そして、メモリサイズです。まだメモリが2GB以上ということはそれほど多くはありませんが、ファイルサイズに関しては2GB以上のものも少なくありません。例えば、TV番組を録画した動画ファイル、DVDのイメージ等々。今回は、2GB以上の大規模ファイルを扱うためLSFについて説明します。

最近のLinuxやBSDだと、デフォルトでカーネルは2GB以上のファイルにLSFとは対応していますし、プログラムも対応しています。NFS(Server/Client)等のデーモン、Appach等のサーバ、cp、cmp等のfileを扱うプログラム等々。そのため、Linuxをデフォルトのままデスクトップとして使っている間は、あまり大規模ファイルのサポートについてはあまり意識する必要はないかもしれません。

しかし、後からプログラムをソースからmakeしてinstallする場合や、自ら開発する上ではこの2GBの壁について意識する必要があります。これを意識せずにコンパイルを行うと、2GB以上のファイルアクセスができなかったり、時には思わぬバグを引き起こしたりする危険性があります。

大規模ファイルアクセスのための仕様はLFS仕様(Large File Summit specification)として規定されたものがあり、Linux(glibc)等もこれに従っています。まずこのLFS仕様を説明します。

現行APIの拡張

従来のファイルアクセスのインタフェースでは、各パラメータは32bit値になっているため、2GB以上の大規模ファイルを正しく扱えません。そのため、LSFでは、このようなファイルに対して処理を実行できない場合や属性を正しく表現できない場合は、適切なエラーとして処理するようになっています。たとえば、open()は、2GB 以上のファイルに対してはエラーとなり、errnoにEOVERFLOW に設定します。

移行用API (transitional API)

LFS は、32bitから64bitへの移行用として、従来の32bitアクセスのAPIとは別に、それぞれのAPIに対応する64bit版のAPIを定義しています。例えば、open()に対するopen64()、seekに対するseek64、stdio.h系のAPIに関しても同様に、fopen()に対するfopen64()等 。これに伴って方の方もオフセットoff64_t が定義されています。

コンパイル環境

◎通常のコンパイル環境 (regular compilation environment)
これは既存のコンパイル環境であり、通常の32bit版のAPIがそのまま使用されます。

◎移行用コンパイル環境 (transitional compilation environment)
通常の32bit版のAPIに加えて、移行用の64bit版API使用可能になります。従来のプログラムには影響を与えませんが、64bit対応するためには、明示的にopen64()等を使用する必要があります。
_LARGEFILE64_SOURCEマクロを1に設定することによって、64bit版APIが使用可能になります。

◎「大規模ファイル」コンパイル環境 (`large file' compilation environment)
この環境では、ファイルアクセスの全APIが64bit対応になります。従来のAPIは全て64bit版にマップ(リダイレクト)されます。具体的には、open()コールはopen64コールにマップされます。この環境では、型定義も64bit版に置き換えられるので、従来のプログラムをこの環境でリコンパイルする場合は、その影響を考慮する必要があります。
_FILE_OFFSET_BITSマクロに64を定義することによって、この環境になります。

gccで大規模ファイル対応のコンパイル

最近のgcc(glibc)ではLSF使用に対応しています。よって、プログラムを2GB以上のファイルに対応させる場合は、makefile等で、
CPPFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
等と書いてやればOKです。

4797328355【関連書籍】
GCC GNU C Compiler―Manual & Reference 遠藤 俊徳
プログラミング言語C ANSI規格準拠 B.W.カーニハン D.M.リッチー
Cプログラミングの落とし穴 A.コーニグ
Linux マルチメディアソフト集

手堅い見積もりが遅れを生む - セーフティの弊害

「予定より早く作業を終わらせても、最初のステップはそれを報告しないからです。現状の仕組みでは、作業を早く終わらせても何もご褒美はもらえないんです。いやそれどころか、ペナルティーが課されます。」
エリヤフ・ゴールドラット 『クリティカルチェーン

4478420459「なぜ、プロジェクトは予定通りに進まないのか?」。「予定通り進まないのがプロジェクトだ」と言う人もおられるでしょう(^^;)。最近読んだ「クリティカルチェーン - なぜ、プロジェクトは予定通りに進まないのか?」という書籍は、そんな「プロジェクトマネジメント」における常識に挑戦する書籍です。この手の本では、久々に共感するところの多かった影響を受けた書籍なので、紹介したいと思います。

この本、著者はTOC(制約条件の理論)の提唱者で、そのTOCを小説仕立てで解説した「ザ・ゴール ― 企業の究極の目的とは何か」がベストセラーになったエリヤフ・ゴールドラット氏です。「ザ・ゴール」は邦訳もベストセラーになったのでご存知の方も多いと思います。その後、「ザ・ゴール2 思考プロセス」「チェンジ・ザ・ルール」と続編が続いており、本書は「ザ・ゴール4」のような位置付けです。今回は、ザ・ゴールからの主題であるTOCをプロジェクトマネジメントに適用させたものです。

プロジェクトマネジメントといってまず出てくるのはPMBOK。もともとアメリカの非営利団体PMIがまとめたプロジェクト管理に関する知識体系ですが、いまや事実上の世界標準です。最近では研修に取り入れている企業も多いのではないでしょうか。プロジェクトマネジメントを系統的に捉える体系として、有用だと思います。PIMBOKに対し、本書で提案されている手法「クリティカルチェーン」の面白いところは、TOCの適用という点もさることながら、人間心理の特性を重視している点です。

セーフティ - 手堅い見積もり

中でも私が思わずなるほどと思ったのはプロジェクトの工数見積もりにおける「セーフティ(safety)」に関する考察です。ここでいうセーフティとは、あるステップを完了するのに必要な予想工数のマージン・余裕量のようなものとして定義されます。
工数見積もりの際に「これくらいでもできるかもしれないけど、念のためこれくらいにしておくか」という時の、
(念のためこれくらい) - (これくらいでできるかもしれない)
という量です。実際、開発ステップでは外的要因や想定外の障害があるため、ある程度のこのようなマージンを見積もりに入れることが多いです。

過剰なセーフティ

本書では、セーフティは大抵は8割くらいの確率で終わるくらいの量で見積もりをあげるだろうとされます。しかも、この8割の確率で終わるという工数は、5割の確率で終わる工数に比較して、2倍以上になるといいます。にわかには受け入れがたい数字ですが、場合によっては当てはまる気もします。
実際、プログラミングフェーズでは、何の障害もなくすんなり終わってしまった作業も、その見積もり時には、実際にかかった工数の2倍以上で工数を見積もっていたということはあるでしょう。これは特に、工数の小さいステップで顕著です。例えば、うまくいけば2時間程で終わる工数を1日といってしまうこともあるでしょう。このような丸めを入れてしまうのもよくある話です。
そう考えると、ステップを細かく割りすぎると、工数に余分なセーフティを与えてしまう可能性があると考えられます。正確な見積もりをしようとする行為が不確定性を高める。不確定性原理のようなものです。

セーフティの浪費

ここで疑問が出ます。では、なぜプロジェクは遅れるのか?セーフティがあるのならむしろ早く終わるのでは?と。

理由は簡単です。浮いた時間が有効に使われないためです。なぜか?これは、年末の道路工事のようなものです。予算を使い切らないと次年度の予算が削られるかもしれない、だから、予算を使い切るために必要のない公共事業を行うというやつです。開発業務の場合、あまり早く仕上げてしまうと、次回からさらに無理なスケジュールを要求されるかもしれない、だから報告しない。さらに言えば、残業代が少なくなれば収入も減るかもしれない。このような心理的な作用によって、セーフティは無駄に浪費されるというのです。

こう書くと保身のためにさぼっているように思えますが、実際そのようなつもりのない人でも、浮いた時間でコードのリファクタリングをしたり、念入りなテストをしたり、ドキュメントを整備したり。やることはいくらでもあるので、決してさぼっていなくても、浮いたセーフティは消費されることは確かに多いでしょう。

マイルストーンをなくす!

では、どうすればいいのでしょうか。本書では、まず細かいマイルストーンをなくすところからはじめます。そして個々のステップは最小の見積もりでスケジュールを立てる。細かいマイルストーンはなく、大きな単位でのおしりや、複数の作業が合流するところだけにポイントを置く。この時、個々のステップはぎりぎりの見積もりで引かれたものなので遅れる可能性は従来より高い。そこで、このポイントに大き目のバッファを置く。とまぁ、こんな感じです。
個々の「予定」を守ることは単なる局所最適に過ぎません。そこに目を奪われて全体としての「予定」が遅れないようにしようというのが主旨なのです。


とりあえずセーフティについて簡単に触れましたが、この他にも興味深い考察がなされています。興味を持たれた方は是非一読をお勧めします。私は、本書で得た考え方を自分の仕事に取り入れていきたいと思っています。

最初からベストのスケジュールをひけば、遅れることがあるのは仕方有りません。しかし、それを許容する風土がなければこのような管理は難しいでしょう。勿論、そのためにバッファを設けたりするのですが、この「予定より遅れる」ということについて、周りに納得してもらうのは少々頑張らないといけないかもしれませんね (^^;)

447837449X 【関連書籍】
クリティカルチェーン―なぜ、プロジェクトは予定どおりに進まないのか? E・ゴールドラット 三本木亮
最速で開発し最短で納めるプロジェクト・マネジメント―TOCの管理手法“クリティカル・チェーン” 村上悟 井川伸治
PMプロジェクト・マネジメントクリティカル・チェーン 中嶋秀隆 津曲公二
プロジェクトマネジメント標準 PMBOK入門 広兼修
ザ・ゴール ― 企業の究極の目的とは何か エリヤフ・ゴールドラット 三本木亮
デスマーチ 第2版 ソフトウエア開発プロジェクトはなぜ混乱するのか E・ヨードン

Linuxインストールメモ - NTFS・無線LAN・ワイドディスプレイ

自分の経験は、どれほど小さくても、百万の他人がした経験よりも価値ある財産である。
レッシング
dellcampaign10_125x125法人向け
最近我が家のノートPCを買い換えました。機種はDELLのINPSPIRON 710m。デフォルトOSは当然のようにWindows XPですので、早速Linuxをインストール。久々ということもあって、いくつか戸惑ったところをもありましたので、メモも兼ねて記事にしておこうと思います。ポイントは、
  • NTFSパーティションの変更
  • 無線LANの設定
  • ワイドディスプレイの設定
といったところです。

■ディストリビューションの選択

最初、手元にあったVine Linux 3.1をインストールしようとおもったのですが、なぜかインストーラが「install exited abnormally」のログを出して以上終了してしまいます。テキストモードでも同様。 特にVineに強いこだわりがあるわけではないので、Fedora Code 4にしました。kernelも2.6系だしパッケージも新しいので結果的には楽そうだというのもあったので。

■NTFSパーティションのリサイズ

買ってすぐのパーティション構成は、Windows XPがインストールされたNTFSパーティションが1つだけ。まずはLinuxインストール用のパーティション確保からです。今まではFIPSというツールでパーティション分割していたのですが、残念ながらNTFSには未対応。GNUPartedというツールもありますがこれも駄目。

qtparted 結局、NTFSパーティションを分割(リサイズ)するツールは、ntfsresizeとそのフロントエンドであるQTPartedを使いました。Linux上で動作するツールで、簡単にパーティション操作ができるツールです。でも、今からLinuxを入れようとしているので、この場合Linuxはインストールされていません。
よって、ここは1CD/DVDのみで起動できるLinuxであるKNOPPIXが使えます。公式サイトからISOイメージをダウンロードしてCDに焼いて起動。手元にisoイメージを焼くソフトがなかったので、フリーのDeepBurnerを使いました。
ちなみに、私が使ったのはKNOPPIX 4.0 日本語版でしたが、QTPartedはデフォルトでメニューにも含まれていました。GUIなので使い方は簡単です。あらかじめNTFSパーティションをデフラグしておき、あとはメニューに従って操作するだけ。使い方は、「QTParted パーティション設定ツール」が参考になります。
これで、NTFSパーティションを縮めてやれば、開いたところにLinuxをインストールすることができます。Windows XPのみしか使用しない人でも、データ用のパーティションを別に区切っておくことで、後々再インストール等の必要性が出た時には有効です。

※実はDELLの直販だと、パーティションを最初から区切ってくれるサービスも選択できたのですが、有料だったので選択していませんでした。

■無線LANの設定

Windowsのデバイスマネージャで見ると、無線LANアダプタは「Intel(R) PRO/Wireless 2200BG Network Connection」。Fedora Coreなら新しいデバイスドライバも入っているだろうということで起動してみますが、 ipw2200は入っており、ハードウェアの認識もされているようですが、demesgで起動ログを見るとファームウェアのロードに失敗したいうようなログがでています。
ipw2200: Intel(R) PRO/Wireless 2200/2915 Network Driver, 1.0.0
ipw2200: Copyright(c) 2003-2004 Intel Corporation
ACPI: PCI Interrupt Link [LNKE] enabled at IRQ 10
ACPI: PCI Interrupt 0000:02:01.0[A] -> Link [LNKE] -> GSI 10 (level, low) -> IRQ 10
ipw2200: Detected Intel PRO/Wireless 2200BG Network Connection
ipw2200: ipw-2.2-boot.fw load failed: Reason -2
ipw2200: Unable to load firmware: 0xFFFFFFFE
ipw2200: failed to register network device
ipw2200: probe of 0000:02:01.0 failed with error -5
driverのホームページを見ると、firmwareは別途用意する必要があるようです。
ダウンロードして、hotplug用のディレクトリ(Fedoraなら/lib/hotplug)に置いてやった上で再起動すると、無事動作しました。 もちろん、WEP等の設定は別途必要です。
(参考)Fedora core 3でIntel PRO/Wireless 2915ABGを使う

■ワイドディスプレイの設定

インストールも済んで、無線LANも無事動いたので、早速Webをブラウジングして見る。???。どうも表示が横長になっています。Xorgの設定は、ちゃんとワイド仕様(WXGA:1280x800)になっています。
どうもワイド表示のためにはビデオBIOSを上書きする必要があるようです。ビデオBIOSの書き換えは855resolutionというツールでできます。インストールして、起動時に書き換えるようにしてやると、正常に表示されるようになりました。
(参考)855resolution

【関連リンク】
KNOPPIX Japanese Edition
Deep Burner (窓の杜)
QTParted パーティション設定ツール
1台のPCでLinuxとWindowsを共存するには? (デュアルブート編)
Intel® PRO/Wireless 2200BG Driver for Linux

【関連書籍】
がんがん使おうPartition Magic
Knoppix Hacks―カスタマイズとシステム管理のテクニック カイル・ランキン
今すぐ使えるLinux KNOPPIXコンプリートガイド 鎌滝雅久 柘植昭秀
Fedora Core4ビギナーズバイブル 大津真 向井領治 まえだひさこ
人気エントリ
最近の記事
本のおすすめ

4274065979

4844337858

482228493X

4904807057

4873114799


最近のコメント
Links
プロフィール
  • Author:proger
  • 組み込み関係で仕事してます
ブログ内検索