2018年3月10日土曜日

gdbによるQtプログラムのデバッグ

GUIを使わないプログラムなのに、Qtを使いまくっているプログラムがあって、それのデバッグしてて困ったことを。
Qtには、STLより効率がいいとのことで同様のQVector, QLIstが実装されています。同じように使えますが、困ったことにgdbでbreakして変数の中身を見ようとしてもエラーがでてきて見えません。
サンプルのプログラムをいかに示します。

  #include <qlist>
  #include <iostream>

  int main()
  {
    QList< QString> list;

    list << "1st" << "2nd" << "3rd";

    for (int i=0; i<list.size(); i++)
    {
      std::cout << list[i].toStdString() << std::endl;
    }

    return 0;
  }

これでgdbによりfor文のところでbreakして、list[0]の中身を見たいと思います。


(gdb) p list[0]
Could not find operator[].

なんか怒られました。どうもQtのテンプレート定義のoperator []に関する多重定義のところで問題が起きているようです。ちなみに、list自体をprintすると以下の様になります。

(gdb) p list
$15 = {> = {}, {p = {static shared_null = {ref = {atomic = {\
_q_value = -1}}, alloc = 0, begin = 0, end = 0, array = {0x0}}, d = 0x604ee0}, d = 0x604ee0}}

かなり複雑な構造をしているようですが、"d"というメンバがいるのはわかります。Stackoverflowなんかで調べても、中々ヒットせず、唯一呪文のようなものがひっかかり、それが正解でした。以下にそれを示します。


(gdb) p ((QString)list.d->array[0]).toStdString()
$17 = "1st"

要は、"d"というポインタのメンバにarray[]で配列にしているということのようです。それを強引にテンプレートで定義したQString型だとして、toStdString()関数をCallしてやれば、QListの中身も表示できます。

なんというか、こんな手間をかけないとデバッグできないならSTLを素直に使ったほうがいいんでないか?という感じです。


PS
QListはコンテナ・クラスですが、通常このてのものはテンプレートを使い、内容物の型を定義するものです。ところが、Qtは上記のarrayのところを(void*)で定義しているものですから、こんなややこしい事になっています。素直に全部テンプレートで実装してくれれば、こんな面倒なことにならずに済むのですが、Qtは様々なコンパイラに対応しています。テンプレートはc++の第3版で正式に定義されましたが、それまで定義があいまいなところがあり、実装がコンパイラ毎にバラバラな時代が10年くらい続いた記憶があります。今でも、時折、コンパイラが変わると、テンプレートまわりで修正が必要なことが発生したりします。(10年以上前は、大騒ぎでした)おそらくそれを嫌ったのと、とにかく速度を稼ぎたかったんでしょうね。(void*)で定義したほうが、圧倒的に速いですから。(そのかわり、バグが入り込みやすく、面倒はプログラマが見ないといけません。)
ちなみにQtCreatorのデバッグ設定がきちんとできていれば、こんな面倒なことはする必要はありません。GUIは使わない組み込みに近いプログラムを作るのに、Qtの一部だけを使っている場合の特殊な状況の話です。

2018年3月5日月曜日

Qtの開発環境(Windows)

相変わらずQtの開発環境づくりに苦労しています。Qtのデフォルトの言語の設定がg++らしく、WindowsでもMinGWにすれば簡単なんですが、やはりVisual Studioにしたい。
どうも、MSがVisual Studioの外部ツールと連携する際のAPIを変更したらしく、これまでのQtで配布していたAddInが使えなくなってます。
色々調べていたら、VStoolというのがあるのでそれを入れれば、Visual StudioでQtの開発ができるとの情報がありました。早速入れてみると、一瞬はうまくいったようなのですが、すぐにダメになりました。このあたりの理由はよくわかりませんが、ちょうどWindowsの更新が煩雑にあった頃のため、何かまたAPIに変更があったのかもしれません。

QtのHPを調べると、何とVisual Studioとの連携をするVStoolはcommercialライセンスにしかなくなっています。(この前、DLできたのはギリギリのタイミング?)
仕方ないので、Qt Creatorの環境を作ります。一方、Visual Studioの方についたQtのAddInは削除する方法が見つかりません。気持ち悪いので、TotalUninstallerというツールでVisual Studioの環境をバッサリ削除し、再インストールしました。

何だかんだと苦労しましたが、いったんきれいな状態にマシンをしてから再度Qtをインストールするとうまくいきました。Qt Creatorの設定画面でもきれいにVisual Studioが認識されています。
色々やっていた時に、WDKをインストールしてあるせいか、デバッグもきちんとできました。