2009年08月12日
山本先輩からコラムを1本いただきました。ありがとうございます。
元々、ミステリーが好きでよく本を読んでいたのですが、最近本の読み方が大きく変化しました。
実際には、物理的な本は読まずに、T-01A(ドコモのWindowsモバイル携帯)を使って読書しています。
続きを読む
元々、ミステリーが好きでよく本を読んでいたのですが、最近本の読み方が大きく変化しました。
実際には、物理的な本は読まずに、T-01A(ドコモのWindowsモバイル携帯)を使って読書しています。
2009年08月10日
C99 の規格が成立してから 10 年が経つわけですが、VC++ 2008 では ANSI C89 (ISO C90) までしか対応しておらず、C99 は未対応のようです。
次期の VC++ 2010 でも状況は変わらないようです。(ベータ版のマニュアルですが。)
http://msdn.microsoft.com/ja-jp/library/02y9a5ye(VS.100).aspx
やはり C# や .NET をプッシュする Microsoft 的には、OS の根幹を支える C++ はともかく、いまさら C はどうでも良いという扱いなのでしょうか。KMCでは、現在でも C はバリバリの現役なので、少し寂しいところです。
ちなみに VC++ にも、GCC と同様に独自の拡張機能が含まれており(ただし、GNU C のような派手な (?) 拡張は存在せず、独自の解釈的な拡張が多いようです)、/Za で ANSI C/C++ と互換性の無い機能を無効にできるそうです。(GCC の -ansi -pedantic 相当。)
「/Za、/Ze (言語拡張機能の無効化)」
http://msdn.microsoft.com/ja-jp/library/0k0w269d.aspx
「Microsoft C/C++ の拡張機能」
http://msdn.microsoft.com/ja-jp/library/34h23df8.aspx
VC++ の拡張機能を有効にする /Ze オプションは、VC++ 2008 で付けると「cl : コマンド ライン warning D9035 : オプション 'Ze' の使用は現在推奨されていません。今後のバージョンからは削除されます。」という警告が出ます。
次期の VC++ 2010 でも状況は変わらないようです。(ベータ版のマニュアルですが。)
http://msdn.microsoft.com/ja-jp/library/02y9a5ye(VS.100).aspx
やはり C# や .NET をプッシュする Microsoft 的には、OS の根幹を支える C++ はともかく、いまさら C はどうでも良いという扱いなのでしょうか。KMCでは、現在でも C はバリバリの現役なので、少し寂しいところです。
ちなみに VC++ にも、GCC と同様に独自の拡張機能が含まれており(ただし、GNU C のような派手な (?) 拡張は存在せず、独自の解釈的な拡張が多いようです)、/Za で ANSI C/C++ と互換性の無い機能を無効にできるそうです。(GCC の -ansi -pedantic 相当。)
「/Za、/Ze (言語拡張機能の無効化)」
http://msdn.microsoft.com/ja-jp/library/0k0w269d.aspx
「Microsoft C/C++ の拡張機能」
http://msdn.microsoft.com/ja-jp/library/34h23df8.aspx
VC++ の拡張機能を有効にする /Ze オプションは、VC++ 2008 で付けると「cl : コマンド ライン warning D9035 : オプション 'Ze' の使用は現在推奨されていません。今後のバージョンからは削除されます。」という警告が出ます。
2009年08月07日
2009年08月07日
少し前の話になりますが、いただいたコメントをきっかけに、puts になぜ改行が付くのかというネタについて調べていた時、面白い論文を教えてもらいましたので紹介します。
"C and the AT&T Unix Port -- A Personal History", Stephen C. Johnson (翻訳)
http://roguelife.org/~fujita/COOKIES/HISTORY/USENIX/johnson.html
続きを読む
"C and the AT&T Unix Port -- A Personal History", Stephen C. Johnson (翻訳)
http://roguelife.org/~fujita/COOKIES/HISTORY/USENIX/johnson.html
続きを読む
2009年08月05日
AndroidのSDKではgoldfishという仮想ハードウェアをqemuで動作させています。この環境は実際のハードウェアがなくても動作させることができるのでとても便利です。goldfishはCPUがARMv5TEアーキテクチャのarm926なのですが、これをARMv6アーキテクチャのarm1136に置き換える実験をしてみたところ意外にすんなり動きました。
その手順をここで紹介します。
2009年08月03日
また pre K&R C の話です。
pre K&R C の時代は、return 文が取る式を () で囲むことが文法上必須でした。その時代の習慣を引きずったためか、K&R (第1版) でも return 文の後の式を括弧で囲っていたようです。(私は第2版しか所有していないので確認できないのですが。)
そのため、今でも括弧を付ける人もいるようです。一方、括弧を付けると return を retuan のようにタイプミスした時に関数呼び出しとして解釈されてしまい、コンパイルエラーにならない(リンク時にはエラーになる)ために良くないと主張する人などもいるようです。いずれにせよここらへんの話は、IDE やエディタがキーワードをハイライトしてくれるようになった現在では、好みの問題の範囲と言えるでしょう。
http://www.math.utah.edu/computing/compilers/c/Ritchie-CReferenceManual.pdf
しかし、そもそも私には、この () が pre K&R C で必須だった理由がわかりませんでした。最後に ; が必須なのですから、この括弧があることにより、特にパーシングに対して有利ということもありません。続きを読む
pre K&R C の時代は、return 文が取る式を () で囲むことが文法上必須でした。その時代の習慣を引きずったためか、K&R (第1版) でも return 文の後の式を括弧で囲っていたようです。(私は第2版しか所有していないので確認できないのですが。)
そのため、今でも括弧を付ける人もいるようです。一方、括弧を付けると return を retuan のようにタイプミスした時に関数呼び出しとして解釈されてしまい、コンパイルエラーにならない(リンク時にはエラーになる)ために良くないと主張する人などもいるようです。いずれにせよここらへんの話は、IDE やエディタがキーワードをハイライトしてくれるようになった現在では、好みの問題の範囲と言えるでしょう。
http://www.math.utah.edu/computing/compilers/c/Ritchie-CReferenceManual.pdf
return ;
return ( expression );
しかし、そもそも私には、この () が pre K&R C で必須だった理由がわかりませんでした。最後に ; が必須なのですから、この括弧があることにより、特にパーシングに対して有利ということもありません。続きを読む
2009年07月31日
KMC のデバッガを一番使っているのは、実は KMC の開発スタッフなのかもしれません。
開発スタッフのディスプレイを覗き込むと、常に PARTNER が起動しています。PARTNER でデバッグし、PARTNER からエディタを起動してソースコードを修正し、PARTNER から make を打ち、ロードし、実行する。もはや完全に PARTNER が OS (shell) のような感じになっています。
KMC には、製品は社内で使い込んで十分に揉んでから出荷するという文化があります。マイクロソフトは、このことを 「ドッグフードを食べる」と表現しているようです。
参考 :「マイクロソフトが社員に勧める“ドッグフード”栄養学」
http://japan.cnet.com/interview/story/0,2000055954,20060067,00.htm
(私は Joel Spolsky の本でこの言い回しを知りました。)
自分たちで日常的に使うことにより、使いにくいところや不具合を改善していくことこそが、良い製品を作るためには必要不可欠なプロセスだと思います。そもそも、社内の人が難しすぎて使えなかったり、不具合が多くて使ってくれないような製品が売れるわけがありません(笑)まずは社内の人に使っていただけるところまで持っていくのが、製品開発の第一の壁です。
最近 koba さんが、exeGCC のテストプロセスの一部に、私の開発している CPU シミュレータを利用してくださっています。膨大な数の GCC のテストスイートを常に通してくださることにより、シミュレータに対する自信が深まりますし、koba さんも実機に JTAG をつなぐ手間なく、多くの CPU でテストを行うことができるという Win-Win の関係が築けています。大変うれしいことです。
開発スタッフのディスプレイを覗き込むと、常に PARTNER が起動しています。PARTNER でデバッグし、PARTNER からエディタを起動してソースコードを修正し、PARTNER から make を打ち、ロードし、実行する。もはや完全に PARTNER が OS (shell) のような感じになっています。
KMC には、製品は社内で使い込んで十分に揉んでから出荷するという文化があります。マイクロソフトは、このことを 「ドッグフードを食べる」と表現しているようです。
参考 :「マイクロソフトが社員に勧める“ドッグフード”栄養学」
http://japan.cnet.com/interview/story/0,2000055954,20060067,00.htm
(私は Joel Spolsky の本でこの言い回しを知りました。)
自分たちで日常的に使うことにより、使いにくいところや不具合を改善していくことこそが、良い製品を作るためには必要不可欠なプロセスだと思います。そもそも、社内の人が難しすぎて使えなかったり、不具合が多くて使ってくれないような製品が売れるわけがありません(笑)まずは社内の人に使っていただけるところまで持っていくのが、製品開発の第一の壁です。
最近 koba さんが、exeGCC のテストプロセスの一部に、私の開発している CPU シミュレータを利用してくださっています。膨大な数の GCC のテストスイートを常に通してくださることにより、シミュレータに対する自信が深まりますし、koba さんも実機に JTAG をつなぐ手間なく、多くの CPU でテストを行うことができるという Win-Win の関係が築けています。大変うれしいことです。
2009年07月30日
2009年07月29日
PARTNER(ARM) のマニュアルを編集していた際、mmu コマンドに /T というオプションを見つけました。マニュアルの説明を読んでもよくわからなかったので先輩に聞いてみたところ、これは TCM (Tightly Coupled Memories) という、ARM コアの内部に存在する超高速メモリ (SRAM) を操作するためのオプションなのだそうです。
TCM は、要するに、ユーザが読み書きできるキャッシュメモリのようなものなのだそうです。容量は小さい (10 数 KB ほど) のですが、DRAM の初期化が済んでない状況でも使えるので、開発の初期段階でちょっとデバッガや簡単なプログラムを動かしてみたい時などに重宝するそうです。また、OS などのシステムソフトウェアの高速化の際にも有用です。(こちらの方が一般的な用途。)
TCM は全ての ARM コアに存在するわけではなく、オプション的に実装されるものなのだそうです。あまりアプリケーションプログラマは恩恵を受けられない機能ですし、SRAM は回路が大きくて実装コストが高いため、実装されないケースも多そうです。特殊な用途の TCM よりも、同じ SRAM を実装するならば、より大きなキャッシュを実装してくれた方がうれしい技術者が多いと思います。
しかし、CPU が速くなれば、相対的にメモリアクセスがボトルネックになりますから、シリコンが余ってきた状況ではおいしい場面も出てくるかもしれません。組み込みの世界では、必ずしも絶対性能は重要ではなく、過去のソフトウェア資産やコストパフォーマンスが重要視されます。ARM 9 ファミリーなどの少し古い v5 アーキテクチャもまだまだ現役です。プロセッサの加工技術が向上すれば、同じアーキテクチャを実装したとしても、シリコンの面積が小さくて済むので、どんどんシリコンが余ります。そのため回路の 1 チップ化 (SoC) を進めたり、コアの数を増やしたりしているようなのですが、TCM のような SRAM もどんどん大きくなっていくのかもしれません。
また、iPhone や Android などが普及し、LLVM などの動的最適化技術 (JIT をより一般的にしたような技術)が進歩すれば、プログラマが意識しなくても、勝手に TCM を使って高速化してくれたりとかいう未来が来るかもしれません。
TCM は、要するに、ユーザが読み書きできるキャッシュメモリのようなものなのだそうです。容量は小さい (10 数 KB ほど) のですが、DRAM の初期化が済んでない状況でも使えるので、開発の初期段階でちょっとデバッガや簡単なプログラムを動かしてみたい時などに重宝するそうです。また、OS などのシステムソフトウェアの高速化の際にも有用です。(こちらの方が一般的な用途。)
TCM は全ての ARM コアに存在するわけではなく、オプション的に実装されるものなのだそうです。あまりアプリケーションプログラマは恩恵を受けられない機能ですし、SRAM は回路が大きくて実装コストが高いため、実装されないケースも多そうです。特殊な用途の TCM よりも、同じ SRAM を実装するならば、より大きなキャッシュを実装してくれた方がうれしい技術者が多いと思います。
しかし、CPU が速くなれば、相対的にメモリアクセスがボトルネックになりますから、シリコンが余ってきた状況ではおいしい場面も出てくるかもしれません。組み込みの世界では、必ずしも絶対性能は重要ではなく、過去のソフトウェア資産やコストパフォーマンスが重要視されます。ARM 9 ファミリーなどの少し古い v5 アーキテクチャもまだまだ現役です。プロセッサの加工技術が向上すれば、同じアーキテクチャを実装したとしても、シリコンの面積が小さくて済むので、どんどんシリコンが余ります。そのため回路の 1 チップ化 (SoC) を進めたり、コアの数を増やしたりしているようなのですが、TCM のような SRAM もどんどん大きくなっていくのかもしれません。
また、iPhone や Android などが普及し、LLVM などの動的最適化技術 (JIT をより一般的にしたような技術)が進歩すれば、プログラマが意識しなくても、勝手に TCM を使って高速化してくれたりとかいう未来が来るかもしれません。
2009年07月28日
2009年07月27日
C の規格に関するちょっとした話です。
今まで、extern が付いていない最上位宣言での変数宣言(グローバル変数)は、全て定義宣言になるのだと思っていたのですが、厳密には異なるそうです。
(1) と (2) は、単に初期値が与えられているかいないかだけの違いで、どちらも定義に見えます。
ところが、厳密には (2) だけが定義宣言で、(1) は仮定義という扱いになるのだそうです。続きを読む
今まで、extern が付いていない最上位宣言での変数宣言(グローバル変数)は、全て定義宣言になるのだと思っていたのですが、厳密には異なるそうです。
int x; /* (1) */
int y = 0; /* (2) */
extern int x; /* (3) */
(1) と (2) は、単に初期値が与えられているかいないかだけの違いで、どちらも定義に見えます。
ところが、厳密には (2) だけが定義宣言で、(1) は仮定義という扱いになるのだそうです。続きを読む
2009年07月24日
このごろは組み込みソフトウェア開発でも C++ が使われるようになってきました。C から C++ に移行する際、おそらく誰もが一度は引っかかるのではないかという C++ の挙動について書きます。続きを読む
2009年07月23日
CNET Japan : Linuxの脆弱性を突くゼロデイエクスプロイトが公開に
Linux Kernel の脆弱性により、見慣れない GCC のコンパイルオプションが話題になっています。恥かしながら、私は今回の一件で始めて知りました。GCC の online manual を見る限り、少なくとも GCC 3.0.4 からは存在するオプションのようです。
GCC Manual 3.10 Options That Control Optimization -fdelete-null-pointer-checks
マニュアルの説明を読むと、既に一回ポインタを間接参照した後の NULL チェックは無意味だから削除するという、何の問題も無い最適化に見えます。
GCC 4.4.1 までは -O2,-O3,-Os で有効になっていたようですが、最新のマニュアルでは(一部のターゲットを除き)全ての最適化レベル(-O0 含む)で有効になると書いてあります。
このリンク元のブログ記事のコード
革命の日々 : 「Linux カーネルの zero-day exploit コード、リリースされる」への余談
Linux Kernel では、ユーザプロセスが 0 番地に mmap を実行することが可能なので、
(1) 0 番地を間接参照しても SEGV が発生しないようにできる。
(2) NULL チェックが GCC の最適化によって削除されてしまっている。
(3) Kernel が 0 番地にアクセスしてしまう。(任意のコードを実行させることができる。)
というメカニズムのようです。なるほど。
私は、これは GCC の問題というよりは、ポインタを NULL チェック無しでいきなり参照している Linux Kernel のコードの問題だと思います。しかし、Kernel などのセキュリティが重要なソフトウェアをビルドする際には、fno-delete-null-pointer-checks を付けておいた方が良さそうです。
# あるいは、NULL チェックが行われていないポインタ参照全てにデフォルトのチェックコードを挿入するようなオプションがあれば良いのかもしれません。
Linux Kernel の脆弱性により、見慣れない GCC のコンパイルオプションが話題になっています。恥かしながら、私は今回の一件で始めて知りました。GCC の online manual を見る限り、少なくとも GCC 3.0.4 からは存在するオプションのようです。
GCC Manual 3.10 Options That Control Optimization -fdelete-null-pointer-checks
マニュアルの説明を読むと、既に一回ポインタを間接参照した後の NULL チェックは無意味だから削除するという、何の問題も無い最適化に見えます。
GCC 4.4.1 までは -O2,-O3,-Os で有効になっていたようですが、最新のマニュアルでは(一部のターゲットを除き)全ての最適化レベル(-O0 含む)で有効になると書いてあります。
このリンク元のブログ記事のコード
struct sock *sk = tun->sk; // initialize sk with tun->skを一見した時、何が問題なのかよくわからなかった (NULL チェックがあろうがなかろうが、NULL ポインタを参照した瞬間に SEGV が発生して kernel panic になるはず、と思った) のですが、kosaki さんの記事を読んで納得。
…
if (!tun)
return POLLERR; // if tun is NULL return error
革命の日々 : 「Linux カーネルの zero-day exploit コード、リリースされる」への余談
Linux Kernel では、ユーザプロセスが 0 番地に mmap を実行することが可能なので、
(1) 0 番地を間接参照しても SEGV が発生しないようにできる。
(2) NULL チェックが GCC の最適化によって削除されてしまっている。
(3) Kernel が 0 番地にアクセスしてしまう。(任意のコードを実行させることができる。)
というメカニズムのようです。なるほど。
私は、これは GCC の問題というよりは、ポインタを NULL チェック無しでいきなり参照している Linux Kernel のコードの問題だと思います。しかし、Kernel などのセキュリティが重要なソフトウェアをビルドする際には、fno-delete-null-pointer-checks を付けておいた方が良さそうです。
# あるいは、NULL チェックが行われていないポインタ参照全てにデフォルトのチェックコードを挿入するようなオプションがあれば良いのかもしれません。
2009年07月22日
ベテラン技術者の S 先輩からコラムを 1 本いただきました。ありがとうございます。
ユーザインターフェースは、人それぞれの好みや世の中の流行などがあって万人受けする設計はとても難しい。色、一つをとっても、KMCのPARTNERでは、Windows Ver3.1の時代に設計されたので、当時Windows Ver 3.1の制約で中間色がほとんど使えなかったため、青色,黄色,黒色などはっきりした色をベースとしました。
現時点では、勿論PARTNERでも中間色設定ができるのですが、新たにその色のデフォルト変更しようとすると、社内でもユーザに確認しても賛成意見(最近のソフトにあわせるべき)と反対意見(PARTNERらしい色使いを残すべき)が拮抗して判断に迷うことも多くあります。
また、好みによってメニューを変えられる機能を付けても、多くのユーザは、標準設定で使うことが多そうです。
そこで、長い間デバッガの開発にたずさわってきた経験とそのデバッガを使ってきた経験からいえることは、デバッグ作業の特性上同じことの繰り返しが非常に多い事です。実は、CUI(コマンド入力)とコマンドヒストリ機能を使うのが早くて便利なのです。
しかし、何度もマウス操作とクリックおよびキー入力、また、表示の変化がディスプレイ上のいろんな場所に変わっていく(メニュー、ダイアログ、タグなど)ので認識に時間がかかります。
一方、CUI(コマンド入力)では、コマンドを覚えないと使えないし、パラメータの意味もマニュアルを見ないと分からない、キーのストローク回数も多いといった問題があって、最近のデバッガではCUIのない(コマンド入力のできない)もしくは使わないデバッガがほとんどです。
KMCのPARTNERでは、GUIの便利な点とCUIの便利な点を組み合わせて利用できる方法は無いものか?と思案した結果。安直ではありますが、GUIでの動作(ロードやブレーク設定など)をCUIのヒストリとして登録する方法をとっています。
これで、最初のロードは、GUIを使ってマウスでファイル指定してロードし、その後のロードは、'L',SHIFT+↑,Enter の3つのキー操作でリロードできるようになりました。社内の開発スタッフは、みんなこの方法をうまく使っています。
このように、GUIだけにたよらず、CUIを組み合わせて使ってみることも良いのではないでしょうか?
参考リンク : PARTNER のデバッグ風景を Flash で見ることができます。
「GUI と CUI の連携」
http://www.kmckk.co.jp/jet/gui_cui.html
「シンボルラインでのシンボル名拡張機能」
http://www.kmckk.co.jp/jet/symbol.html
「関数バックトレースと関数ローカル変数ウィンドウの連動」
http://www.kmckk.co.jp/jet/debugger.html
「モジュールウィンドウからの関数の選択」
http://www.kmckk.co.jp/jet/module.html
ユーザインターフェースは、人それぞれの好みや世の中の流行などがあって万人受けする設計はとても難しい。色、一つをとっても、KMCのPARTNERでは、Windows Ver3.1の時代に設計されたので、当時Windows Ver 3.1の制約で中間色がほとんど使えなかったため、青色,黄色,黒色などはっきりした色をベースとしました。
現時点では、勿論PARTNERでも中間色設定ができるのですが、新たにその色のデフォルト変更しようとすると、社内でもユーザに確認しても賛成意見(最近のソフトにあわせるべき)と反対意見(PARTNERらしい色使いを残すべき)が拮抗して判断に迷うことも多くあります。
また、好みによってメニューを変えられる機能を付けても、多くのユーザは、標準設定で使うことが多そうです。
そこで、長い間デバッガの開発にたずさわってきた経験とそのデバッガを使ってきた経験からいえることは、デバッグ作業の特性上同じことの繰り返しが非常に多い事です。実は、CUI(コマンド入力)とコマンドヒストリ機能を使うのが早くて便利なのです。
- デバッグのファイルロード
- ブレークポイントの設定
- 変数参照
- ファイル参照
しかし、何度もマウス操作とクリックおよびキー入力、また、表示の変化がディスプレイ上のいろんな場所に変わっていく(メニュー、ダイアログ、タグなど)ので認識に時間がかかります。
一方、CUI(コマンド入力)では、コマンドを覚えないと使えないし、パラメータの意味もマニュアルを見ないと分からない、キーのストローク回数も多いといった問題があって、最近のデバッガではCUIのない(コマンド入力のできない)もしくは使わないデバッガがほとんどです。
KMCのPARTNERでは、GUIの便利な点とCUIの便利な点を組み合わせて利用できる方法は無いものか?と思案した結果。安直ではありますが、GUIでの動作(ロードやブレーク設定など)をCUIのヒストリとして登録する方法をとっています。
これで、最初のロードは、GUIを使ってマウスでファイル指定してロードし、その後のロードは、'L',SHIFT+↑,Enter の3つのキー操作でリロードできるようになりました。社内の開発スタッフは、みんなこの方法をうまく使っています。
このように、GUIだけにたよらず、CUIを組み合わせて使ってみることも良いのではないでしょうか?
参考リンク : PARTNER のデバッグ風景を Flash で見ることができます。
「GUI と CUI の連携」
http://www.kmckk.co.jp/jet/gui_cui.html
「シンボルラインでのシンボル名拡張機能」
http://www.kmckk.co.jp/jet/symbol.html
「関数バックトレースと関数ローカル変数ウィンドウの連動」
http://www.kmckk.co.jp/jet/debugger.html
「モジュールウィンドウからの関数の選択」
http://www.kmckk.co.jp/jet/module.html