2 LibreOfficeのデバッグ(初心者向け)
この記事は2人の大学生がLibreOfficeWriterの一部機能を変えようと格闘した記録の2ページ目(全4ページ)です。
大規模ソフトウェアを手探るという授業の一環で行い、そのレポートを兼ねています。
目次
1. 方法を説明する前に
LibreOfficeは前のページでも書いた通り、そのソースコードは膨大です。coreのなかにはさらに多くのファイルがあり、このページやREADMEに書いてあるような分け方をされているようですが、それらをすべて把握するのは極めて困難です。そこでこのページはどのような方法を用いて自分の関心のある機能に迫っていくかを解説します。また、どうやらLibreOfficeはハンガリアン記法という書き方に基づいてコードが書かれていて、これを頭に入れておくと変数がどのようなものを表しているかを推測することができ、コードを読んでいく際に役立つかもしれません。
2. 公式のドキュメントを見て手掛かりを掴もう
いざデバッガを使って、コードを読もう!…とその前に、LibreOfficeが用意しているドキュメントに目を通すことをおすすめします。なぜならLibreOfficeはGUIなので、ただ起動するだけではデバッグは始まりません。どこかにブレークポイントを打って、なおかつそのブレークポイントを通るような動作をさせて初めて、デバッグができるのです。じゃあそれっぽいところにブレークポイントをとりあえず打てばいいじゃん...となるかもしれませんが、なにせソースコードが膨大です。何がなんだかぱっと見ではわかりません。そこで公式ドキュメントをしっかり読んで、ブレークポイントを打つところを探すのです。
ここでは各ディレクトリのおおまかな内容が説明されているので、まず触ろうとしているソフト(Writer,Calc,Impressなど)がどのディレクトリなのかを見つけるといいと思います。例えばWriterならsw、Calcならsc、Impressならsdなどと分かれています。そしてそのドキュメントを読めば、プログラムの構造やメソッドの説明がすべて書いてあるわけではありませんが、その一部を大雑把に知ることができるでしょう。もちろん全てを把握するのは無理です。例えばこれはWriterに使われている全てのクラスを一覧にしたものですが、膨大ですよね。なのでおおまかな説明を読んで、関連しそうなメソッドなど目星をつけたら、ブレークポイントを打ってみて、実際にデバッグを開始することをお勧めします。
例えば私たちの場合は、ここに書いたように初めはWriterのUndoRedo機能に変更を加えたかったため、Writerのswディレクトリの説明をまず読みました。ここではsw内の各ディレクトリについて簡単に説明されていて、Writerの根幹部分はsw/source/core
内に記述されているそうです。またここに、
とあります。Undo機能はUndoManagerというクラスで管理されているとわかったため、これを目星にブレークポイントを打とうと決めました。
そこで、VSCode上での検索機能を用いて、sw/source/core
内でUndoManagerという文字列が出てくるところを検索すると、
のように大量のファイルが出てきます。151件?!と思うかもしれませんが、安心してくだい。ディレクトリをだいぶ絞ったおかげで、13個のファイルしかヒットしませんでした(何も絞らなかったら293個のファイルに3747件と出ます、恐ろしい...)。ここからファイル名的に関係ありそうなファイルに絞り(あとヘッダーファイルもあるのでそれも除外して)、関係ありそうな箇所にブレークポイントをひたすら打っていけばいいのです。今の例では、docundo.cxx
がいかにも怪しそうだったので、その中を見ていった結果、UndoManager::DoUndo
という非常に怪しいメソッドにたどり着きました。よってとりあえずここにブレークポイントを打ちます。
3. デバッガを使いこなそう
ここまでで怪しいメソッドに目星をつけ、ブレークポイントを打つことができました。ここからは実際にデバッガを立ち上げて、デバッグを開始していきます。デバッガでWriterを立ち上げ、実際にaなどを打ったあとにUndoをしてみると、 このように見事止まってくれます。これで本格的にデバッグができますね!
これからはStep InやStep Outなどを駆使してメソッドからメソッドへと飛び移っていき、少しずつプログラムの内容を把握していきます。メソッドや関数の動作を詳細に知りたいときはStep In、関数がどこから呼ばれていてどのような文脈に位置するのかを知りたいときはStep Outを使うイメージです。関数の働きを知る際には左のサイドバーで変数の中身をチェックしたり、ウォッチ式に入れて動作を観察することも有効でしょう。また、それ以外にも気になる関数を右クリックすると、定義や参照元などに移動できます。これらをうまく駆使してデバッグしていきましょう。
ここで、Step Outをしすぎてしまうと、
のような画面にたどり着きます。vcl/unx/gtk3/gtkdata.cxx
のGtkSalData::Yield
というメソッドです。これ以上遡ろうとすると、「例外が発生しました」と出てデバッグができなくなるので、注意してください。このYieldメソッドはユーザーからの入力を常に受け付けているスレッド(だと解釈しています)なので、これ以上は遡ることができないのです。ですが、逆に言えば、このメソッドに行き着くまでに様々なメソッドを経由していて、その中には必ずどこかでUndoやRedoなどの操作を決定している場所などがありますから、一度ひたすらStep Outをクリックし続けて処理の流れを大まかに追うのは、全体の処理の流れがわかりやすくなる点でおすすめです。全体を見た上でどこを具体的に見ていけばいいのかを判断すると作業が効率的になると思います。
ここまでデバッグの一般的な使い方を書きましたが、私たちがデバッガを使った時には作業がスムーズにいきませんでした。困った点としては、
- デバッガで踏み込むとフリーズするときがある(重すぎるから?)
- 関数が多すぎて1つの動作の始めから終わりまでを追うことができない(1つ1つ丁寧に見ると時間が溶けるので、目星をつけて見るしかないですけど、間違ったものに目をつけると相当時間が溶けます!なのでしっかり見極めてください!)
などです。このソフトへの理解がさらに進めばこれらの問題は回避できるかもしれません。
また、ここではデバッグのノウハウをざっくり説明しましたが、実際にどのような思考でデバッグをするかについては、次の記事の4.変更箇所にたどり着くまでが参考になるかもしれません。
4. 参考になるサイト
- core内の各ディレクトリの説明
ここでWriterはsw内に記述されていることとswのおおまかな概要を掴みました。 - 関数が検索できる機能
ほとんど使いませんでしたけど、一応載せておきます。 - Writerに使われている関数一覧
気になったクラスなどの他の関数との関係性を見たいときに使いました。
5. デバッグノウハウまとめ
詳しくは上で説明しましたが、一応デバッグする際に使いそうなツールをここで簡単にまとめておきます。
変化を追いたい変数や、式の値や真偽を知りたいとき
→VSCodeのウォッチ式に入れて観察や、変数の中身を見る定義や参照元をすぐ見たいとき
→関数にカーソル合わせて右クリックで選択する(ctrl+クリックでも参照できる)基本
→Step In、Step Out、Step Over、Continueをしっかり使い分けることと、左のサイドバーで変数の中身を観察すること
→適宜参考になるサイトに載せたサイトなどを見たりしてもいいかも?
という感じです。これはあくまでもこの実験で初めてデバッグを知った私たちが、この実験を通して考えたノウハウなのでいろいろと欠けている部分もあると思いますが、同じような初学者のためになればと思います。