Visual StudioでQtをデバッグする
概要
この記事はQt Advent Calendar 2015 - Qiitaの20日の記事です。19日はIoriさんのQt Champions for 2015に選ばれました! - 理ろぐでした。すごい!!超おめでとうございます!!
さて、今回はQt4の始めのころから気になっていた日本語入力のバグをやっとこさ退治したのでそれにまつわるお話を。今回はInput Method回りのデバッグだったので、トレースポイントを使うためにVisual Studioでデバッグをしていました。Visual StudioでQtアプリケーションをデバッグするための手順や、実際にやった事を書いていきたいと思います。
バグの内容
バグの内容はhttps://bugreports.qt.io/browse/QTBUG-49955のとおりで、こんな風にPre-Editの文字が残ってしまう、というバグです。
変換候補を表示した状態で次の一文字目のキーを押した時のイベントがうまくハンドリングできていない模様。QWindowsInputContextの問題なので、QtのWidgetsおよびQMLの全ての日本語入力で起きていました。
Qt Creatorでは何故かその後ろにテキストカーソルが固定されて、どこを編集しているのか分からなくなるという事態も。
デバッグ環境
Visual Studio Community 2013を使用しました。
キーボードの入力イベントを追いかけたいので、ブレイクポイントは使えません(フォーカスがVSに移って別のイベントが出てしまうので)。qDebugを埋め込むという手も有るけど、デバッグ出力の内容を変えるたびに再ビルドしないといけなくなります。それなら(最近やっと覚えた)トレースポイントの出番です。GDBでも使えるらしいけどIDEから操作できないし。。。
環境構築
とりあえずこれだけ必要だと思います。括弧内は私が実際に使用した環境です。
- Visual Studioのインストール(Visual Studio Community 2013)
- Qt Visual Studio Add-inのインストール(Qt5 Visual Studio Add-in 1.2.4)
- Qtのソースコード準備(Qt 5.5.1 MSVC 2013 32bit opensource)
ターゲットはQWindowsInputContext(5.5/Src/qtbase/src/plugins/platforms/windows/qwindows.vcxroj内)なのでqtbaseだけビルドできればOKとしました。
Visual Studio
Add-inの使えるものが良いです。Qt Visual Studio Add-inが入れられないとQStringの中身とか見るのが大変で泣けます。最近はCommunityが使えるので嬉しいです。
Qt Visual Studio Add-in
VSで.proファイルを開いたり、QStringやQListの中身を見やすく表示したり、といった機能を提供してくれるらしいです*1。とにかくインストール。Qtダウンロードページの下の方、Other Downloadsに有ります。
http://www.qt.io/download-open-source/#section-7
Qtのソースコード
ソースコードをダウンロードしてきてConfigureしてビルドすれば良いのですが、色々苦い思い出があるのでインストーラが入れてくれた環境を使おうと思い、5.5をインストール(srcのインストールを追加選択)した環境を使おうと思いました。でも結構ハマりました。
結果的にはQt5.5の32bit版をインストールして、5.5/msvc2013/libディレクトリを5.5/Src/qtbase/libにコピーして何とかなりました。
- 始めは64bitをインストールしたのですがプロジェクト設定は32bitになっていて64bitのLIBやDLLを参照にいっちゃったりしてしっちゃかめっちゃか。面倒くさいのでやりなおし。
- Src/qtbase/libに入っていないqtfreetyped.libとかが無い、といってリンクエラーになります。プロジェクトの出力先が5.5/msvc2013/のbinとかlibになっているのに参照先は5.5/Src/qtbase/libになっていました。
デバッグ
とりあえずqwindowsinputcontext.cppのあちこちの関数にトレースポイント貼りまくって、呼ばれる関数や参考になりそうな変数を探しました。それからトレースポイントに条件設定したりして絞り込みました。トレースポイントはプログラムを実行しながら付けたり消したり、一時的に無効にしたり、出力内容を変更したりできるのでこういう時には本当に便利だと思います。頻繁に使う場合はTools-Option-Environment-KeyboardでEditorContextMenus.CodeWindow.Breakpoint.InsertTracepointに適当にキーを割り当てましょう。
呼び出し元関数を出力したり、書式指定でdefine名を表示したりできるのは今回初めて知りました。参考にさせて頂いたブログズミさんに感謝。
ブログズミ: [Visual Studio]コードを修正せずに変数の値をログ出力する方法
ブログズミ: [Visual Studio] ウォッチをより便利に使う10の書式
今回のMVPトレースポイントさんはこちら
Location: qwindowscontext.cpp, line 1272
Condition: et==InputMethodRequest||et==InputMethodEndCompositionEvent||et==InputMethodCompositionEvent
Message: et={et}, handled={handled}, message={message}, wParam={wParam}, lParam={lParam}
(書式指定のXとか付けた方が良かった気がしています)
終わりに
ガリガリとコードを書く時はQt Creatorのお世話になる事が多いですが、バグを追いかける時はVSを使う事が多いです。WindowsでQtを使っている(多分少数派の)皆さん、デバッグのお供にVisual Studioはいかがでしょうか。
ちなみにこのバグのパッチは私がpushするbranchを間違えたため5.6には間に合わず5.7でマージされる事になるようですごめんなさいごめんなさいごめんなさい。
追記: たすくせんせーのおかげで、5.6にマージされました。いつもありがとうございます!
明日はynumaさんhttp://qiita.com/ynumaのQt Testです。お楽しみに!
*1:今回の環境ではVSに「Qt」メニューが追加されないのでどこから.proファイルを開けばいいのか分かりませんでした。