組込み開発の現場での C と品質と生産性の話をセグメンテーションフォールトの観点で

C で書かれた手作りの自然言語処理のアプリケーションをソースコードごと頂き、使わせて頂いていたのですが時々セグメンテーションフォールトで止まります。開発者に心当たりがないか訪ねたところいろいろあるようなのですが gdb で調べろとのこと。コードを頂いている以上はもっともな話なのでちょっと見てみます。ちょと手順をおさらい。
1) そのままでは core ダンプしてくれないので
ulimit -c unlimit
で、フォールト時に core を吐いてもらうようにします。で、アプリケーションを実行して、セグメンテーションフォールとが起きて core を吐いているのを確認します。20年程前は宴会でお酒飲みすぎて吐いたりすると 「core 吐いてる」とか良くいったものなのですが、最近の Linux は core を吐かない設定がデフォルトなせいか、あまり聞かなくなりました。
2) gdb 実行ファイル coreファイル
3) bt でトレース、あれれ、fwrite の中で落ちてる??なにを喰わせたんだろ?
4) frame フレーム番号で呼び出し元を見る、ありり?ただの文字列書いてるだけなんだけど?
5) p 変数名 で、ファイルポインタをみると番地とは思えない値。ここで、スタック壊されたなと見当をつける
6) b 行数 で、fopen() でファイルポインタを取得しているところにブレークポイントを当てる
7) r 実行時引数列 で再実行。6) であてたブレークポイントでとまる
8) n で一個すすめて fopen() を実行して、取得したファイルポインタの値を見る
9) watch ファイルポインタ==取得した値 でワッチポイントを設定
10) c 実行をコンティニューし、ファイルポインタが壊された所でとまる
11) 配列の代入をしているので p で添字を確認

と、ある意味 C で開発している人にとっては日常の風景なのですが配列のオーバーランをしている場所を突き止めて、サイズを修正して make します。

15分ぐらいの作業なのですが、これが 15 分ぐらいの作業ですんでいるのは相手が PC の小さなアプリケーションだったからで、例えば携帯電話の開発みたいなリソース制約のある環境での大規模開発の場合、そもそもデバッグシンボル付きのバイナリがメモリに乗り切らない等の理由で gdb が使えないことが多々あり、メモリ設定をいじってある特別のデバッグ用ボードを用意するとか、あとは gdb をあきらめて ICE でデバッグするなどどんどん大掛かりな話になって、機材の準備とか、デバッグ用のバイナリの再ビルドに8時間かかるとか大事になったりするのですが、それですめばまだいいほうでそういうデバッグ用機材の用意もできない事情がある開発現場も多々あり、ひたすら printf を追加して、8時間かけて再ビルドして、見当をつけて printf を追加して、、、というのを2ヶ月も続けているうちに出荷遅延の大問題になって睡眠なしで上記作業をつづけた挙げ句に、配列のオーバーランが原因とか、スタック変数を return で返してたとか、そういういつもの原因が見つかったりします。

で、しみじみと思ったのは、デバッガのありがたさではなくて^^:それは当然として C のようなコンパイル言語の生産性の低さです。ソフトウェア開発の生産性(productivity)を、ときどきコーディングの生産性で議論しているのを見かけることがありますが、C で書くと20行必要なコードが Haskell だと2行だとかいうあの議論ですが、実際、開発にかかる時間のほとんどがデバッグと手直しと保守改良であることを考えると、書きやすいことはあまり生産性と関係なく、むしろ書いたものが普通に動く、動かなくてもデバッグが速いことが生産性に一番響いてきます。特に大規模な組み込み開発という、コードサイズは大きいのに、ハードウエアリソースが限られている開発を人海戦術でこなしている場合に、このデバッグ地獄で発生する人月のロスは開発費を大きく押し上げることになるでしょう。

C で書いたコードがバッファオーバーランしやすいのはそのとおりだけど、設計時にしっかりとサイズを見積もっておけばいいはなしであって、ランタイムでチェックするのは実行効率をさげる。Cで書いてある事と品質とは関係なく、それはプロセスの話では?という意見もあるかもしれません。そもそもソフトウェアの品質とはISO9126 で列挙してもらっているように「機能性」「信頼性」「使用性」「効率性」「保守性」「移植性」の複合的なモデルであらわされるものです。関係ないですがソフトウェアの開発規模も複合モデルであらわされるものなのですが、ソフトウェアの難しさは目に見えないことの他にこういう複合性があるような気がします。さらに関係ないのですがこういう複合モデルというか彼の言い方をつかうと「コンストラクティブな」モデルはたいがいいいだしっぺがバリー・ベームだったりしますね。
さて、その「移植性」を考えた時、ソフトウェアは設計当初の用件を超えた環境で手直しなしに動くことも品質として期待されます。設計当初は 5000 個のファイルが処理できればいいや、ということで配列のサイズを 5000 にしてしまうと、それは後で、ファイルが10000個開けなければならない環境に移植した際に問題を起こし、それはデバッガが使える環境なら 15分で治せるような問題かもしれないので意識に載らないかもしれませんが、多くの実開発の現場では2ヶ月かかる問題の原因になっていたりします。保守性と移植性の観点で、静的な言語は、型チェックがあるという利点がある(ダイナミックな言語でも素性のいいものには動的型推論がありますが)を割り引いても、全てをコンパイル時に決定してしまいランタイムの処理が薄いことが原因で品質の問題を起こしやすく、それが生産性に影響を与えているのではないか、というのが私の印象です。

しばらく javascriptphp にどっぷりつかっていて久しぶりに gcc を使った感想として、やっぱり動的な言語は生産性がいいなあと。大体、開発が地獄になる原因のほとんどがデバッガが使えない事と、そのために入れた printf の結果を見るまでのコンパイルの待ち時間だったりすることを考えると、デスマーチの原因はインタプリタではなくコンパイラをつかう事にあるんじゃないか、などと乱暴なことを考えたりもした一日でした。

言語批判は宗教戦争の火種になりかねないところがあって危険な話題だったかなと思いつつも、Cには宗教戦争する信者もいないかなと思いつつ。ちなみにコンパイラ言語の型チェックのありがたさも理解してますし(php で たとえば WebServiceAPI を叩いていて、動き出すまでの修正は、型チェックしてメッセージだしてくれてたら一発だったのに、というのが多々あります)オブジェクトの実行効率の良さも、フロー解析して最適化してくれるコンパイラのおかげと理解してます。それはそれとして、まあなんというか。

バーコードと携帯の話し(2)、バーコードは商品の背番号

2013年のパリ〜ニースが始まりました。ユーロップカーはさい先よくプロローグを制して今年も調子がいいですね。
フランスではときどきユーロップカーの小型トラック(レンタルトラック?)を見かけるのですが、壁には等身大の選手が三人、ローラー台を回していて、そのローラーがトラックのエンジンになっているようなトリックアートが描いてあって、ちょっとユーモラスというか、逆に普通のトラックよりもパワフルでアルプスでもロアやボクレールみたいにガンガン昇っていけそうななんか面白い塗装です。

以下、物流の世界の人たちには常識以前であるような大前提のお話なのですが、バーコードは流通する商品の背番号で、バーコードから商品を一意に特定することができます。
バーコードにもいろいろな種類や使い方があって、学校図書館公共図書館が貸し出し管理用に貼っているバーコード(New7コード)や、スーパーで生鮮食料品に貼っているバーコード、レシートの下に書いてあるバーコード(トランザクションコード)など商品の背番号でない使い方のバーコードも多くあるので分りにくいのですが、本の背表紙に印刷されている ISBN コードや、レトルト食品等の商品パッケージに印刷されているバーコード(JANコード、グローバルにはEANコード)は、世界中で一意に商品が特定できるように管理されています。
これらの管理は流通システムの合理化及び標準化を目的とする"GS1"という国際団体(本部はブリュッセルにあります)及び各国の下部団体(日本では”一般財団法人流通システム開発センター”)によって行われています。
ISBN コードについては本を一意に特定するコードとして広く一般にも認知されているようですが、JANコードについてはまだご存知ない方も多いように見受けられます。

つまり、DoCoMo 仕様として JAN コードを読むことのできる携帯電話は、実は読み取りの速度や精度を問題としないのであれば、流通する商品の背番号を処理する能力をもともと持っているわけなのです。あまり使われているようにも見えず、ちょっともったいない気がします。

次回は、iアプリを作らなくても、携帯でJANコード(やISBNコード)を処理するシステムを簡単につくることができることを紹介します。

紹介いたしました団体のURL は以下です

GS1
http://www.gs1.org/

一般財団法人 流通システム開発センター
http://www.dsri.jp/

バーコードと携帯の話し(1)、そもそも携帯でバーコードが読める事をご存知でしたでしょうか

読み込みの速度も精度も専用端末と比べて劣るのですが、数年前から従来型携帯電話(平たく言ってガラケー)やスマホJANコード等の一次元バーコードが読めるようになっています。モバイルでは逆にQRコードが読めることが広く知られているものの、一次元バーコードも実は読めるということのほうがあまり認知されていないようです。これは、読み込んだQRコードに書かれている URL にジャンプさせるという機能が「テキスト表示」機能として i-mode 仕様の一部になった歳に革新的なサイネージの手段として当時は広く受け入れられたことにより早くから広く認知されるものとなったものの、一次元バーコードについては個人利用での有効な応用が無かった(これについて次回以降で考察します)こと、速度や精度の問題で(他にも根本的な理由があるかもしれませんが)既存の流通システムに応用できなかったことなどが原因であまり使われる機会に恵まれず、認知されなかったのではないかと考えます。

尚、このバーコード及びQRコードi-mode 仕様は OMA の mobile code 仕様に影響を与え(というか、実際はどういう経緯だったのか良く知らないのですが、良く言えば既存の仕様にたいして車輪の再発名をしない、悪くいうとコピペ?とも感じられる仕様が見受けられる OMA の他の仕様のなりたちから類推するに、i-mode 仕様を取り込んだ、もしくは寄書されたという感じだったのでしょうか?)、mobile code の white paper の reference として、公開されている i-mode 仕様の英語版へのリンクが紹介されています。
つまり、最近のOMA 仕様を実装するグローバルな端末でも、QR コードに書かれた URL をブラウザでジャンプできるようになってきている訳で、実際にヨーロッパやアジア諸国でも QR コードをつかったサイネージを最近みかけるようになってきていて、日本発の仕様が「お、こんなところで使われてたか!」とちょっとワクワクすることがあります。逆に日本では、フェイクサイトとか、電車内でカメラを使うことへの抵抗感などからQRのサイネージ利用が減ってきているように感じますので、このあたりは文化というか国民性の問題が出ているみたいです。

明日以降、せっかく携帯電話で利用できる JAN コードについて、流通系での利用ではなく、個人ユースでの利用を考察してみます。


言及した仕様へのリンクは以下です。

DoCoMo
・作ろうiモードコンテンツ / 知りたいiモード技術情報を選ぶ / バーコード
http://www.nttdocomo.co.jp/service/developer/make/content/barcode/function/index.html


OMA
・White Paper on Mobile Codes
http://technical.openmobilealliance.org/Technical/release_program/docs/CopyrightClick.aspx?pck=MobileCodes&file=V1_0-20081024-A/OMA-WP-MobileCodes-20081024-A.pdf

ストリーミングが正常に再生されない理由

このネタ、まだかいてませんでした ^^;
動画のストリーミングが正常に再生されない原因を調べてほしいというご相談を受ける事が良くあります

正常に再生できない、という現象にもいろいろあって、絵が乱れる(箱のようなノイズが入る、絵が止まる、絵が飛ぶ)、音が乱れる(音が飛ぶ、止まる)、そもそも再生を開始しない、etc

まず多いのが、同じコンテンツであっても正常に再生できる時は再生できるのだけど、時々出来なくなる。できなくなる時間帯がだいたい同じ。もしくは逆でほとんど再生できないのだけどたまに再生できることがあって、再生できる時間帯がだいたい同じ。
こういうのは原因がほとんど WiFi の干渉によるネットワーク性能の劣化で、現象が出ている時のネットワークのスループットを測ってみると、コンテンツのビットレート以上のスループット(がネットワークに確保できていないとストリーミングは成立しません)が出ていません。こういう時は、ストリーミングのクライアントは流れてくるコンテンツを十分な量になるまで溜めるために再生を止めようとします。これをバッファリングと呼ぶのですが、ネットワーク性能が出ていない時はこれが頻繁に発生して再生が正常に進みません。

そもそも WiFi は干渉を起こしやすく、マンション等でも隣や上下の解の WiFi と干渉を起こす事がよくあり、とくに近所の WiFi が大量のデータを通信している時(たとえばストリーミング再生を始めた等)に自分の WiFi の通信速度が著しく低くなり、1MBps を下回ってしまうようなことも良くあります。
ちなみに WiFi の干渉状態のチェックには専用の機材は不要で PC があれば十分です。いろいろなアプリがあるのですが私は InSSIDer というアプリをつかっています。また、ネットワークのスループットの測定ですが UNIX に古くからある iperf がシンプルですが使いやすいです。Windows の場合は Cygnus の Network tool のなかに iperf があるのでそれを使うとインストールも楽です。Android の iperf アプリケーションもいくつかあるので、私は Windows 上の Cygwin の iperf をserver にして、Android をクライアントにしてスループットを測るようにしています。

次に多いのはストリーミングアプリケーションの問題で、ハードウェアアクセラレータ(この辺り、ストリーミングの仕組みについてもいつか解説したほうがいいかもしれないと思ってきました)を使わないタイプのアプリケーションがコンテンツのデコードに CPU を使い切ってしまい、デコードが間に合っていない場合。
これは端末の CPU 消費量を表示するとすぐにわかるのでこちらも簡単です。

あと、そもそもコンテンツの種類がストリーミングに対応していない、というのもたまにあります。このあたりは本当にストリーミングの仕組みと関係してくる話なので、後日、詳しく解説させていただきます。

以上のどれでもなかったとき、これが厄介で、想像もつかないようなことが結局原因なのですが、何日も現場につめて、いろいろなログをとったりしてだいたい2週間ぐらい調べて原因が特定されることになりますが、こういうのは本当にまれで、30回調べて一回あるかないか、という頻度です。

尚、上記の3つの「よくある」ケースですが、実は一般家庭だけでなく、こういう機器のメーカーでもときどき起きていて、現場に見に行ってみると同じフロアにテスト環境として大量においてある WiFi の AP 同士が干渉してたというような一目現場を見ただけで原因の見当がついてしまうようなこともよくありました。お話をうかがってみると「なぜか昼休みや深夜は現象がでない」とのこと、これもテスターの人たちがお昼ご飯たべにいったり家にかえってしまってたりして他の WiFi の AP が動いていないから競合がおきないのが理由ですね。

こんな感じなのでストリーミングが正常に再生されないときは、コンテンツの形式云々よりもまず、WiFiスループットを実際に測ってみることをおすすめいたします。

何のために Obfuscation を学ぶのか

一年以上ブログかいてませんでした ^^;;

以前、obfuscation についてブログにかいた時に紹介したネコの海賊の表紙の教科書「Surreptitious Software」がアマゾンジャパンで "Information Theory" の洋書の38位になっていたので、高い本なのにびっくりしてます。あれやっぱり日本語訳だしたら売れるようなきがするのですがピアソンさんどうでしょ?私のでよければすぐに訳つくりますが。

で、皆さんどういうモチベーションであの本を買っているのだろうか?と、紹介した張本人がいうのもなんですが気になりまして。というか、高い本なのでちょっと心配になってきたというか、例えば大学のソフトウェア工学(もしくは科学)の研究室の学生が勉強する為に買っているのならそれは良い事だなぁと思います。GMAT の教科書みたいに分厚い本ですが、あれ一冊、ざざっと読んでしまう優秀な学生さんがソフトウェア開発の現場に出てくると頼もしいと思います。

もともと DTCPIP のコンテキストで書いてたので、もしかして DTCPIP の実装をしようというモチベーションで、obfuscation の実装を勉強するために買われている方がいるのではないかとちょっと心配になりました。ソフトウェア工学における品質および生産性の向上に一番効果的なのは”再利用”なのですが、DTCPIP についてはすでに多数のライブラリ製品が存在する(オープンソースはないと思います。鍵が手に入らないので)ので、なにも自分でオブフスケーションからつくらなくても単にプロダクトを作る目的ならそういうライブラリを買ってきてリンクしてテストすればそれで良いと思います。ただし、単にベンダーに投げっぱなしにするのではなく、どういうオブフスケーションが実装されているのか発注元として理解しておく、ということだとそれはすばらしいと思います。発注元として十分な知識をもったうえでベンダに質問するとベンダ側の怪しげな実装のボロがみえてくるかもしれません。

もしくは DTCPIP ライブラリのベンダになろうとして obfuscation を実装しようとされている方。今だと obfuscation の library 製品がいくつかあります。特に商用のものでは DTCPIP の実製品での使用実績を歌っているようなものも検索すると出てくるので、そのあたりの製品の利用を検討してみるのもいいかもしれません。

あと、リンクプロテクションを欺きたいという目的で obfuscation の勉強をするのはあまり意味がないようなきがします。商用の obfuscation library の実装は教科書に載っている以上にえげつないものもあって、私も評価したことがあるのですがデバッグされていることを検知するとと処理をとめてしまうのではなく、無意味な演算が永遠に続くフェイクの処理に分岐させて無駄なデバッグを延々とさせて消耗させるという攻性障壁みたいな実装もあります。そんなのがあると知っていたところでその罠に嵌ることを防げるわけでもないですし。手をださないほうが安全な気がします。
そもそも暗号ライブラリの obfuscation を見破って、鍵を抜いて、その鍵でなりすまし実装をつくって、コンテンツを抜く、というのがちょっとあるいみ生真面目すぎるというか遠回りすぎる気がします。苦労して鍵など抜かなくても、ハードウェア機能と連携した真面目なメディアプレイヤーを除き、平文化した後のコンテンツのデコード、レンダリングを OS のノンセキュアなメディアフレームワークにゆだねざるを得ず、つまりノーガードなメディアフレームワークに流しているのだから単にそれを抜き取ればいいだけの話です。つまりきっちり守られてるリンクプロテクションなど攻撃しなくても、メディアフレームワークに渡ってしまった後のコンテンツをシステムから抜くほうが楽だというある意味あたりまえの話ですね。ちなみに真面目なメディアプレイヤーはどうやっているのかというと、一言でいうとメディアフレームワークデコーダ、レンダラの間でリンクプロテクションをやり直しているという感じで、OS レベル(Windows のProtected Environment等)やチップレベル(TEE等)で提供される機能をつかってメディアフレームワークデコーダ、レンダラとの間で認証と鍵交換を行い、デクリプテッドコンテンツを内部用にまたエンクリプトして流通させます。このあたりはハードウェアやプラットフォーム(チップのベンダ)によってインターフェースが異なるため、製品毎の一品ものの実装を真面目にされているようです。

そんなこと思ってたら本当にそういう脆弱製を抱えた商品がいくつかあるようで、筐体外してジャンパ線をハンダ付けすると平文化したコンテンツがそのまま流れてくるようなセットトップボックスが売られているらしく、いくらソフトウェアでセキュリテリーを真面目に実装してもシステムの設計が間違っているとどうしょうもないという分りやすい見本でした。

備忘録: rqrcode-rails3 で少しはまる

ものすごく間が開いてしまいました、このアカウントまだ生きてたんですね ^^;
その間、久しぶりに Symbian のお仕事を楽しませていただき、燃え尽きておりました。
Symbian とはほんとに古いお付き合いだったので、5年ぶりぐらいですけど関われてうれしかったです。

今日の話は rqrcode-rails3 をつかってみて2時間ほどはまったので、document が少ないモジュールなのでどなたかの参考になればと思い。

インストール方法は下記 Git の README.rdoc 通り gem の install だけなのですが、

 https://github.com/samvincent/rqrcode-rails3

手順中の下記一文を読み飛ばしてしまったため、はまってしまいました。
If you want to use the PNG format, you will have to have ImageMagick installed on your system.

ちょっと恥ずかしいですね。この状態で How to use のように respond_to を書いて url に .svg をつけてchrome で開くとQRコードが表示されるのですが、.png では rails がちょっとわかりにくいエラーになりました。

尚、同じ失敗をしてる方がほかにもいらっしゃったみたいです。
https://github.com/samvincent/rqrcode-rails3/issues/7


今日は(も?)しょうもない次回からは DLNA と似てるように見えて全然違う Apple AirPlay の話や、DLNA での livestreaming の話とかをまたしていきたいと思います。

Android 端末のバッテリーの保ちが悪い理由を想像して見ました

今回こそヨタ話しです。技術的な根拠もなく単なる想像です。

Android 端末のバッテリーの保ちが、ガラケーと比較して大変わるいです、これは想像ではなく事実ですね。ガラケーだと一度、満充電にしておくと初期の電池だと一週間ぐらい充電なしで平気だったりするのですが、android だと朝、満充電でも夕方にはバッテリーがきれてたりして、ただの文鎮になってたりします。

これがちょっと不思議で、Linux ガラケーandroid スマホで部材がそんなに違うわけでもないし、なんでこんなに違うんだろうと不思議に思っていたのですが、ちょっとおもいつきました。
androidLinux kernel のソースコードは基本的に Linux プロジェクトのソースコードの git がそのままつかわれています。基本的にといういいかたをしたのは、omap や tegra などはそれぞれ kernel/omap.git や kernel/tegra.git といった独自のプロジェクトをもっていますが、それらの git のヒストリーをみてみると、kernel/linux-2.6.git のコピーにいくつかの対応をいれた物のようです。
つまり、PC 用の linux kernel をそのままつかっているようにみえます。

#2011.09.08 今日現在、トラブルによりandroid のコードはみえなくなっています。

常に電源に接続されていて、とにかく高速であることをもとめられる PC と、大事なバッテリーを節約してつかわなければならない携帯では、kernel のリソースマネジメント戦略は全く違います。処理負荷が低いときにクロック周波数をダイナミックに下げる、メモリの使用領域が複数のメモリチップに分散しないようにまとめた上でつかっていないメモリチップの給電を止める等、PC ではかんがえられないような制御が携帯では必要になるのですが、もしかしたらそういった省電力制御が androidlinux kernel にははいっていないのかもしれません。

尚、あたりまえですが、このような省電力制御をいれることができる場所はカーネルだけです。なぜならドライバではリソースの負荷はわからないので、いつ省電力モードにおとしてよいのかわかりません。年中省電力制御だと高性能チップの意味がなくなります。

自社で省電力対応をした linux kernel を搭載した端末を出す家電メーカーがもし現れれば、ものすごく魅力的な android 端末があらわれそうです。ただ、これは相当勇気と体力のいる作業になりそうですが、というのはカーネルの入れ替えによる影響範囲は製品全体に及ぶため、全機能の再テストが必要になる、というのが携帯電話ビジネスに長い人の平均的な思考回路なのです。

繰り返しますが、本日の話しはただの想像で根拠はありません。関係者から話しをきいたわけでもないですし、カーネルのコードを読んだわけでもありません。もしかしたら、android のバッテリーの保ちがガラケーより悪いということさえ、たまたま私のケータイの巡り合わせが悪かっただけかもしれません。