カレンダー

07月 │2017年08月│ 09月
- - 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 - -

 プロフィール

はしもと

Author:はしもと
ユーザインタフェース系のお仕事をしてます.関心領域は画像処理,拡張現実感,ヒューマンコンピュータインタラクション,エンタテインメントコンピューティングあたり.モノ書きもやってます.

 工学ナビ

工学ナビは工学系の技術のチュートリアルを扱うサイトです.

 作ったもの

 Twitter

 

 天気予報


 ブログ内検索

 カテゴリー

最新コメント

 RSSフィード

 リンク

このブログをリンクに追加する




工学ナビの中の人 はしもとのブログです. いろんなコトを研究的,工学的な視点で見つめます.
スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

ソースリーディングのススメ 人のソースを読む6つのコツ

プログラミングの問題を解決する最短の近道は,人に聞くことではない。
他人が書いた"動く"ソースを読むことだ。

 「○○を作るにはどうしたらいいの?」 「このソフトがやっているこの処理のコードが知りたい」と困ったときは,似たようなことをやっているプログラムのソースを本やネットから探して,それを読むのが一番です.
 今日は自分が求めているコードとそうでないコードが混ざりあっているソースを解読して,目的のコードを探し当てるコツを挙げてみたいと思います.(内容的にはC/C++/VC++寄り)


[1] とりあえず自分の環境でコンパイルして動かしてみる
 拾ってきたソースが自分の開発環境でコンパイルできないと,そもそもそれが自分の環境で動くものなのか確認できません.また,後述する「いじって動かして」をやるためにも,最低限プログラムが動く状態にする必要があります.


[2] プログラマが書いたコメントを読む
 大抵のことはコメントを読めばわかります.ヘッダファイルの上部には注意書きが書かれていることがよくあるので要チェックです.


[3] あらゆる名前(変数名,関数名,ソース名,ヘッダ名)から内容を推理する
 コメントがない場合には,変数名や関数名が貴重な手がかりになります.多くの場合,英語で書かれているので知らない英単語だったら辞書で調べましょう.変数の役割を適当に予想して自分でコメントを書いておくと良いです.

↓こんな風に

int img_width; // 画像の幅?

また,仮にマジックナンバーがあってもひるまずにその値の意味を推理してみましょう.

<例>
width = 1024; // たぶん画面解像度?
height = 768; // たぶん画面解像度?

 意味のある名前の関数が使われている箇所,意味のある名前の変数に値が代入されている箇所などが重要なポイントになってきます.


[4] printf()などの表示関数を使ってコードの動作を追っかける
 デバッグでも使うオーソドックスな手法です.関数の役割がわからないとき,関数がどのタイミングで呼ばれるのかを知りたいときは,積極的に「状態を表示させる」のが一番です.printf(),MessageBox(),TRACE(),OutputDebugString()などの表示関数をソースに書き加えてコンパイルし,プログラムの動作を追っかけてみましょう.

 例えば,ある関数がいつ,何回呼ばれるのかを確認するには,その関数の中で

  printf("関数hogeが呼ばれました");

とトラップを仕掛けて,様子を見ると良いです.


[5] 「コメントアウト→コンパイル→実行」を繰り返して自分が必要としているコードを探り当てる
 いわゆる消去法です.「これは多分関係ない」と思う箇所をちょっとだけコメントアウトしてコンパイルします.コンパイルが通ったら実行して,コメントアウトの前後でどういう部分に変化が出たかを確認します.コメントアウトしたことによってある機能が働かなくなったら,コメントアウトした行が関連していることになります.一気にやらずにちょっとずつやるのがコツです.

 メモリの開放処理などをうっかりコメントアウトしてしまうと,プログラムが落ちたり,OSが落ちることもあるので慎重にやりましょう.

 変数の宣言部をコメントアウトしたときに出るコンパイルエラーは,その変数がどこで使われているか,どこで初期化されているかを示すヒントになります.また,#include の行をコメントアウトしたときに出るコンパイルエラーは,どの関数がどのヘッダで宣言されているかを知る手がかりとなります.


[6] ゼロから作り直してみる
 元のソースをいじり倒しても解読がうまくいかないときは,新しくまっさらなソースファイルを用意して,そこに「少しずつ引越し」していく手があります.

 "引越し"は,そのプログラムのエントリポイント(main関数やWinMain関数)に対して行います.すなわち,元ソースのmain関数に書かれている内容を,新ソースのmain関数に少しずつコピーしていきます(ヘッダファイルなどは後から順次追加).そして「ちょっと移してはコンパイル」を繰り返します.その過程で出現するエラーメッセージに注目します.

以下はVisualC++6.0の例です.

「定義されていない識別子です」
 =変数・関数が宣言されてない
 →元ソース上のどこで宣言されているかを探す

「外部シンボル *** は未解決です」
 →関数の本体が書かれていない(元ソース上のどこかに関数の本体がある)
 →ライブラリがリンクされてない(プロジェクトファイルをチェックしよう)

 こうしてわざとエラーメッセージを出させることで,プログラム中の変数や関数の因果関係,必要なヘッダ・ライブラリがわかります.[5]の消去法に似てますが,こちらは関係ないコードがはっきりわかるのでオススメです.


とまぁ,こんな感じです.
研究でプログラムを書いてる素人なので,ツッコミなどお待ちしてます.


この記事に対するコメント

私はプロファイラを使ってあるパラメタで実行するとどういう経路を通過するのかということや計算の重要なルーチンはどこにあるのかを最初に発見するという方法をよくやりますね.
ソースコードが長い場合はデフォルトのオプションでは殆どの関数が実行されずに終わることもおおいのでこれで見るべきソースの範囲が半分くらいにせばまりますよ.
【2007/03/06 13:57】 URL | #zQHIT1rU [ 編集]

わたしは
とりあえずdoxygenにかけます。
関数/メソッドのコールグラフが出るのでそれなりに分かりやすいです。
【2007/03/07 00:39】 URL | takke #mQop/nM. [ 編集]


プロフェッショナルな方々のコメントをお待ちしておりました!ありがとうございます!

>#zQHIT1rU さん
お恥ずかしい話ですが,プロファイラというものの存在を初めて知り,早速VC++6.0のプロファイラを使ってみました.・・・・・うわー!すげー!いままでどんだけ損してたんだろう・・・

>takkeさん
「doxygen」という文字はときどきライブラリのドキュメントの下のほうで見かけますが,ソース解析&ドキュメント作成ツールのことだったんですね.今度利用してみます.

さほど大きなプログラムを書いたりしてないので記事に書いた方法で間に合ってたんですが,やっぱり玄人は「ツール」を使いこなしてるんですね・・・ こうした開発ツールの機能を使えこなせてる人が周囲にほとんどいないのがなんとも残念です.みんな会社入ったりして覚えてるのかな?
【2007/03/07 01:12】 URL | なおき #F54KmX5Y [ 編集]




この記事に対するコメントの投稿














管理者にだけ表示を許可する


この記事に対するトラックバック
トラックバックURL
→http://kougaku.blog28.fc2.com/tb.php/223-9a0790a7
この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。