デバッグ用ヘルパー
Qt Creator は、Pythonスクリプトを使用して、デバッガバックエンド(現在はGDB、LLDB、CDBがサポートされています)からの生のメモリ内容や型情報データを、[Locals] および [Expressions] ビューでユーザーに表示される形式に変換します。
GDBのプリティプリンタや LLDBのデータフォーマッタとは異なり、Qt Creator のデバッグヘルパーは、ネイティブなデバッグバックエンドから独立しています。 つまり、Linux上のGDB、macOS上のLLDB、Windows上のCDB、あるいはサポートされている3つのバックエンドのうち少なくとも1つが利用可能なその他のプラットフォームでも、同じコードを使用できます。
システムにインストールされている、またはアプリケーションが使用するライブラリにリンクされているデフォルトの GDB プリティプリンタを使用するには、[Preferences ] > [Debugger ] > [GDB ] > [Load system GDB pretty printers] の順に選択します。詳細については、GDB を参照してください。

組み込みデバッグヘルパーのカスタマイズ
組み込みのデバッグヘルパーが読み込まれ、完全に初期化された後にコマンドを実行させることができます。追加のデバッグヘルパーを読み込んだり、既存のものを変更したりするには、Preferences >Debugger >Locals & Expressions に移動し、Debugging Helper Customization フィールドにコマンドを入力してください。

GDBの使用中にシグナル受信に関するエラーメッセージが表示された場合は、そのシグナルを処理するためのGDBコマンドを指定できます。たとえば、次のようなエラーメッセージが表示された場合、SIGSTOP シグナルを無視するようGDBに指示できます:The debugged process stopped because it received a signal from the operating system. Signal name: SIGSTOP 。
GDB が `SIGSTOP ` シグナルを処理しないようにするには、`Debugging Helper Customization ` フィールドに次のコマンドを追加します。
handle SIGSTOP nopass handle SIGSTOP nostop
デバッグ中にアプリケーションがシグナルを受信した直後にメッセージボックスを表示するには、[Preferences ] > [Debugger ] > [GDB ] > [Show a message box when receiving a signal] の順に選択します。
カスタムデバッグヘルパーの追加
独自の型用のデバッグヘルパーを追加するには、コンパイルは不要で、Pythonのコードを数行追加するだけで済みます。スクリプトは、Qtや独自のライブラリの複数のバージョンに同時に対応させることができます。
カスタム型用のデバッグヘルパーを追加するには、デバッガーの起動ファイル(例:~/.gdbinit や~/.lldbinit )にデバッグヘルパーの実装を追加するか、Preferences >Debugger >GDB にあるAdditional Startup Commands 内で直接指定します。
独自のデータ型用のデバッグヘルパーの実装を開始するには、その実装を、Qt インストール先またはスタンドアロンのQt Creator インストール先のshare/qtcreator/debugger/personaltypes.py ファイルに記述してください。macOS では、このファイルはQt Creator アプリケーションパッケージに同梱されており、Contents/resources/debugger フォルダ内にあります。
personaltypes.py ファイルには、1つの実装例が含まれています:
# def qdump__MapNode(d, value):
# d.putValue("This is the value column contents")
# d.putExpandable()
# if d.isExpanded():
# with Children(d):
# # Compact simple case.
# d.putSubItem("key", value["key"])
# # Same effect, with more customization possibilities.
# with SubItem(d, "data")
# d.putItem("data", value["data"])デバッグヘルパーを追加するには:
share/qtcreator/debugger/personaltypes.pyファイルを編集用に開きます。たとえば、WindowsではC:\Qt\Tools\QtCreator\share\qtcreator\debugger内を確認してください。macOSでは、Qt Creator.app/Contents/resources/debuggerを参照してください。personaltypes.pyファイルの末尾に、ダンプ機能の実装を追加します。デバッグヘルパーの実装に関する詳細については、以下のセクションを参照してください。- Qt Creator のインストールを更新する際(たとえば、Qt XMLのインストールを更新する場合など)、
personaltypes.pyが上書きされないようにするには、このファイルをファイルシステム上のQt Creator のインストールディレクトリ外の安全な場所にコピーし、Preferences >Debugger >Locals & Expressions >Extra Debugging Helper でその場所を指定してください。
Qt Creator でデバッグセッションを開始するか、[Debugger Log]ビューのコンテキストメニューから[Reload Debugging Helpers ]を選択すると、personaltypes.py からカスタムデバッグヘルパーが自動的に読み込まれます。
デバッグヘルパーの概要
デバッグヘルパーの実装は通常、単一の Python 関数で構成されます。この関数の名前は `qdump__NS__Foo` とする必要があります。ここで、`NS::Foo ` は検査対象のクラスまたはクラステンプレートです。なお、`:: ` というスコープ解決演算子は、二重アンダースコア `__` に置き換えられます。ネストされた名前空間も使用可能です。関数名の構成には、テンプレート引数は使用されません。
例:
- 型 `
namespace Project { template<typename T> struct Foo {... } }` のデバッグヘルパーを実装する関数の名前は `qdump__Project__Foo` です。 - 型 `
std::__1::vector<T>::iterator` のデバッグヘルパーを実装する関数の名前は `qdump__std____1__vector__iterator` です。
Qt Creatorのデバッガープラグインは、この型のオブジェクトを表示したいときに、この関数を呼び出します。この関数には、以下のパラメータが渡されます:
dDumper型のオブジェクト。これは現在の設定を持ち、 および ビューの一部を表すオブジェクトを構築するための機能を提供します。Locals ExpressionsvalueValue型のオブジェクト。gdb.Valueまたはlldb.SBValueのいずれかをラップしています。
qdump__* 関数は、Locals およびExpressions ビューにおけるオブジェクトとその子要素の表示を構築するために使用される特定の情報を、Dumper オブジェクトに供給する必要があります。
例:
def qdump__QFiniteStack(d, value): alloc = value["_alloc"].integer() size = value["_size"].integer() d.putItemCount(size) if d.isExpanded(): d.putArrayData(value["_array"], size, value.type[0])
注: LLDB および GDB バックエンドの両方で使用可能なダンパー関数を作成するには 、gdb.* およびlldb.* ネームスペースへの直接アクセスを避け、代わりにDumper クラスの関数を使用してください。
デバッグヘルパー内でオブジェクトのベースインスタンスを取得するには、value.base() 関数を使用するか、以下のサンプルコードを使用してください:
def qdump__A(d, value): t = value.members(True)[0].type dptr, base_v = value.split('p{%s}' % t.name) d.putItem(base_v)
デバッグヘルパーは、型名が正規表現に一致するたびに呼び出されるように設定できます。そのためには、デバッグヘルパーの関数名がqdump__ (アンダースコア2つ)で始まる必要があります。さらに、その関数にはregex という3番目のパラメータが必要であり、そのデフォルト値として、型名が一致すべき正規表現を指定する必要があります。
たとえば、Nim 0.12 コンパイラは、コンパイルするすべてのジェネリックシーケンスに、TY1 やTY2 といった人工的な名前を割り当てます。これらをQt Creator で可視化するには、次のデバッグヘルパーを使用できます:
def qdump__NimGenericSequence__(d, value, regex = "^TY.*$"): size = value["Sup"]["len"] base = value["data"].dereference() typeobj = base.dereference().type d.putArrayData(base, size, typeobj)
デバッグヘルパーの実装
デバッグヘルパーは、表示されるデータ項目の説明を、GDB/MI や JSON に類似した形式で生成します。
Locals およびExpressions ビューの各行について、次のような文字列を作成し、デバッガープラグインに送信する必要があります。
{ iname='some internal name', # optional
address='object address in memory', # optional
name='contents of the name column', # optional
value='contents of the value column',
type='contents of the type column',
numchild='number of children', # zero/nonzero is sufficient
children=[ # only needed if item is expanded in view
{iname='internal name of first child',
},
{iname='internal name of second child',
},
]}iname フィールドの値は、オブジェクトの内部名であり、ビュー内でのオブジェクトの表示位置に対応する識別子のドット区切りリストで構成されます。この値が存在しない場合は、親オブジェクトのiname 、ドット、および連番を連結して生成されます。
name フィールドの値は、ビューのName 列に表示されます。指定されていない場合は、代わりに括弧で囲まれた単純な数値が使用されます。
このフォーマットは安定しているとは保証されていないため、ワイヤ形式を直接生成するのではなく、Python Dumper クラスの抽象化レイヤー、具体的にはDumper クラス自体、およびDumper:Value とDumper:Type の抽象化を使用することを強く推奨します。 これらは、iname およびaddr フィールドの処理、単純型の子要素、参照、ポインタ、列挙型、既知および未知の構造体の処理を行うための完全なフレームワークを提供するほか、一般的な状況に対処するための便利な関数も備えています。
CDB をデバッガのバックエンドとして使用する場合、[Preferences ] > [Debugger ] > [CDB ] > [Use Python dumper] を選択することで、Python ダンパーを有効にできます。

以下のセクションでは、qtcreator\share\qtcreator\debugger\dumper.py で定義されている、広く使用されているダンプクラスの一部とそのメンバーについて説明します。
Dumper クラス
Dumper クラスには、汎用的な管理機能、低レベル機能、および利便性向上のための関数が用意されています。
putItem(self, value)- 基本型、参照、ポインタ、列挙型を直接処理し、複合型の基底クラスやクラスメンバを反復処理し、必要に応じてqdump__*の関数を呼び出すマスター関数。putIntItem(self, name, value)- 以下と同等です:with SubItem(self, name): self.putValue(value) self.putType("int")
putBoolItem(self, name, value)- 以下と同等です:with SubItem(self, name): self.putValue(value) self.putType("bool")
putCallItem(self, name, rettype, value, func, *args)- デバッガーのバックエンドを使用して、`value `で指定された値に対して`func`関数を呼び出し、`rettype`を返すようにし、その結果の項目を出力します。ネイティブ呼び出しは非常に強力であり、例えばデバッグ対象のプロセス内の既存のデバッグ機能やロギング機能を活用することができます。しかし、以下の理由から、ネイティブ呼び出しは管理された環境でのみ、かつデータにアクセスする他の手段がない場合にのみ使用すべきです:
- コードの直接実行は危険です。デバッグ対象プロセスの権限でネイティブコードが実行されるため、デバッグ対象プロセスを破損させるだけでなく、ディスクやネットワークにアクセスしてしまう可能性もあります。
- コアファイルを検査している間は、ネイティブ呼び出しを実行できません。
- デバッガ内での呼び出しの設定および実行には、多大なコストがかかります。
putArrayData(self, address, itemCount, type)-addressにある配列のようなオブジェクトのtype型の子プロセスを、itemCountで指定された数だけ作成します。putSubItem(self, component, value)- 以下のコードと同等です:with SubItem(self, component): self.putItem(value)
ネストされた関数呼び出しによって発生した例外はキャッチされ、
putItemによって生成されるすべての出力は、以下の出力に置き換えられます:except RuntimeError: d.put('value="<invalid>",type="<unknown>",numchild="0",')put(self, value)- 出力文字列に直接追加を行う低レベル関数。これは、出力を追加する最も高速な方法でもあります。putField(self, name, value)- `name='value'`フィールドを追加します。childRange(self)- 現在のChildrenスコープで指定された子要素の範囲を返す。putItemCount(self, count)-value='<%d items>'フィールドを出力に追加します。putName(self, name)- `name=''`フィールドを追加します。putType(self, type, priority=0)- フィールド「type=''」を追加します。ただし、type が親のデフォルトの子タイプと一致する場合、または現在の項目に対してpriorityの値がより大きい状態でputTypeがすでに呼び出されている場合は除きます。putBetterType(self, type)- 最後に記録されたtypeを上書きします。putExpandable(self)- 現在の値に対する子項目の存在を通知します。デフォルトでは子項目は存在しません。putNumChild(self, numchild)- 現在の値に対する子項目の存在(numchild> 0)または非存在を通知します。putValue(self, value, encoding = None)- ファイル `value=''` を追加し、必要に応じてその後にフィールド `valueencoding=''` を追加します。valueは、英数字のみで構成される文字列に変換可能である必要があります。実際の値が英数字のみという要件を満たすために何らかの方法でエンコードされる必要がある場合、`encoding` パラメータを使用してエンコーディングを指定できます。 パラメータencodingは、codec:itemsize:quoteという形式の文字列です。ここで、codecは、latin1、utf8、utf16、ucs4、int、またはfloatのいずれかです。itemsizeは、codecによって暗黙的に指定されていない場合、オブジェクトの基本コンポーネントのサイズを指定します。また、quoteは、表示時に値を引用符で囲むかどうかを指定します。例:
# Safe transport of quirky data. Put quotes around the result. d.putValue(d.hexencode("ABC\"DEF"), "utf8:1:1")
putStringValue(self, value)- `QString ` をエンコードし、適切な `encoding` 設定で `putValue` を呼び出します。putByteArrayValue(self, value)- `QByteArray ` をエンコードし、正しい `encoding` 設定で `putValue` を呼び出します。isExpanded(self)- 現在の項目がビュー内で展開されているかどうかを確認します。createType(self, pattern, size = None)- `Dumper.Type` オブジェクトを作成します。具体的な動作は `pattern` によって異なります。patternが既知の型の名前と一致する場合、その型を表すDumper.Typeオブジェクトが返されます。patternがネイティブバックエンドで認識される型の名前である場合、返される型はネイティブ型を表します。- それ以外の場合は、
patternを使用して、構造体のフィールドを記述する一連の項目を以下のように解釈し、型記述を構築します。フィールド記述は、以下の1つ以上の文字で構成されます。q- 符号付き 8 バイト整数値Q- 符号付き 8 バイト整数値i- 符号付き 4 バイト整数値I- 符号なし 4 バイト整数値h- 符号付き 2 バイト整数値H- 符号なし2バイト整数b- 符号付き1バイト整数値B- 符号なし1バイト整数d- 8バイトのIEEE 754浮動小数点数f- 4バイトのIEEE 754浮動小数点値p- ポインタ、すなわち、ターゲットアーキテクチャに応じた適切なサイズの符号なし整数値@- 適切なパディング。そのサイズは、前後のフィールドおよびターゲットアーキテクチャによって決定される<n>s- <n> バイトの BLOB。アライメントは暗黙的に 1 となる<typename>- 名前を持つDumper.Typeによって決定される、適切なサイズおよび適切なアラインメントを持つblobtypename
Dumper.Type クラス
Dumper.Type クラスは、データの一部の型(通常はC++のクラスや構造体、構造体へのポインタ、あるいは整数型や浮動小数点型などのプリミティブ型)を記述します。
型オブジェクト、つまり `Dumper.Type ` クラスのインスタンスは、デバッガーのバックエンドによって作成されます。通常は、デバッグ対象のバイナリに組み込まれている、あるいは同梱されているデバッグ情報を評価することで作成されますが、デバッグヘルパーによってオンザフライで作成されることもあります。
Qt Creator は、ほとんどの Qt クラスについてオンザフライで型情報を提供するため、オブジェクトのイントロスペクションを目的として Qt のデバッグビルドを使用する必要がなくなります。
Dumper.Type クラスには、以下のように広く使用されているメンバ関数があります。
name- この型の名前を文字列として返します。型が匿名の場合は `None` を返します。size(self)- この型のオブジェクトのサイズをバイト単位で返します。bitsize(self)- この型のオブジェクトのサイズをビット単位で返します。alignment(self)- この型のオブジェクトに必要なアライメントをバイト単位で返します。deference(self)- ポインタ型の場合はそのポインタの参照先となる型を返し、それ以外の場合は `None` を返します。pointer(self)- この型への間接参照が可能なポインタ型を返します。target(self)- 配列型に対しては要素の型を、ポインタおよび参照に対しては間接参照後の型を返す、利便性を高めるための関数です。stripTypedefs(self)- この型がエイリアスの場合、その基底型を返します。templateArgument(self, position, numeric = False)- これがテンプレート型の場合、positionにあるテンプレートパラメータを返します。numericがTrueの場合、そのパラメータを整数値として返します。fields(self)- この型の基底クラスおよびデータメンバーを記述する `Dumper:Fields` のリストを返します。
Dumper.Field クラス
Dumper.Field クラスは、型オブジェクトの基底クラスまたはデータメンバーを記述します。
isBaseClass- 基底クラスとデータメンバーを区別します。fieldType(self)- この基底クラスまたはデータメンバーの型を返します。parentType(self)- 所有型を返します。bitsize(self)- このフィールドのサイズをビット単位で返します。bitpos(self)- 所有型におけるこのフィールドのオフセットをビット単位で返します。
Dumper.Value クラス
Dumper.Value クラスは、C++クラスのインスタンスやプリミティブデータ型などのデータ片を表します。また、ファイルの内容、非連続なオブジェクト、コレクションなど、メモリ上に直接的な表現を持たない人工的な項目を表すのにも使用できます。
Dumper.Value には、常にDumper.Type が関連付けられています。値の実際のデータを表す主な表現は、以下の2つです。
- Pythonバッファプロトコルに準拠したPythonオブジェクト(Pythonの
memoryviewなど)またはbytesオブジェクト。size()は、この値の型のサイズと一致する必要があります。 - 現在のアドレス空間内のオブジェクトの先頭へのポインタを表す整数値。オブジェクトのサイズは、その型の
size()によって指定されます。
Dumper.Value の内部表現に関する知識は、通常、そのデバッガヘルパーを作成する際には必要とされません。
Dumper.Value クラスのメンバ関数およびプロパティは以下の通りです。
integer(self)- この値を、適切なサイズの符号付き整数値として解釈した結果を返します。pointer(self)- この値を、現在のアドレス空間内のポインタとして解釈した結果を返します。members(self, includeBases)- この値の基底オブジェクトおよびデータメンバーを表す `Dumper.Value` オブジェクトのリストを返します。dereference(self)- ポインタを表す値の場合は、その参照先値を返し、それ以外の場合は `None` を返します。cast(self, type)- この値と同じデータを持つが、型がtypeである値を返します。address(self)- この値が現在のアドレス空間内の連続した領域で構成されている場合はそのアドレスを返し、それ以外の場合はNoneを返します。data(self)- この値のデータを、Pythonのbytesオブジェクトとして返します。split(self, pattern)- この値のデータから、patternに基づいて作成された値のリストを返します。許容されるパターンは、Dumper.createTypeの場合と同じです。dynamicTypeName(self)- この値が基底クラスのオブジェクトである場合、その動的型の名前を取得しようと試みます。それが不可能な場合は、Noneを返します。
子要素および SubItem クラス
データが初期化されていない場合や破損している場合、子項目の作成を試みるとエラーが発生する可能性があります。このような状況で正常に回復させるには、Children およびSubItem コンテキストマネージャーを使用して、ネストされた項目を作成してください。
Children のコンストラクタ__init__(self, dumper, numChild = 1, childType = None, childNumChild = None, maxNumChild = None, addrBase = None, addrStep = None) は、1つの必須引数と複数のオプション引数を受け取ります。必須引数は、現在のDumper オブジェクトを指します。オプション引数を使用して、子要素の数numChild 、およびそれぞれの子要素の型childType_ とchildNumChild_ を指定できます。maxNumChild が指定された場合、その数だけの子要素が表示されます。これは、そうでなければ処理に過度に時間がかかる可能性があるコンテナの内容をダンプする際に使用すべきです。 パラメータaddrBase およびaddrStep を使用すると、子ダンプ機能によって生成されるデータ量を削減できます。n 番目の子項目のアドレスがaddrBase + n * addrStep と等しい場合、その項目のアドレスの表示は抑制されます。
例:
if d.isExpanded(): with Children(d): with SubItem(d): d.putName("key") d.putItem(key) with SubItem(d): d.putName("value") d.putItem(value)
なお、これは次のように記述するとより便利になります:
d.putNumChild(2) if d.isExpanded(): with Children(d): d.putSubItem("key", key) d.putSubItem("value", value)
Copyright © The Qt Company Ltd. and other contributors. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.