ネイティブ C++ の式
デバッガーは、Microsoft および ANSI C/C++ の大部分の式を認識します。 デバッガーには、式をより安全かつ便利に評価するための組み込み関数とコンテキスト演算子も用意されています。 このトピックでは、次に挙げるような、注意が必要な C++ 式の制限事項について説明します。
コードやスクリプト、またはマネージ コード式には、コンテキスト演算子やほとんどの書式指定子を使用できません。 コンテキスト演算子や書式指定子は、ネイティブ C++ の式エバリュエーターに固有の要素です。
このセクション
デバッガーの組み込み関数による状態の保持
コンテキスト演算子によるシンボルの指定
ネイティブ C++ の式の制限事項
アクセス制御
あいまいな参照
匿名の名前空間
コンストラクター、デストラクター、および変換
継承
インライン関数とコンパイラ組み込み関数
数値定数
演算子関数
オーバーロード
優先順位
シンボルの書式
型キャスト
デバッガーの組み込み関数による状態の保持
デバッガーの組み込み関数を使用すると、アプリケーションの状態を変更せずに、式の中で特定の C/C++ 関数を呼び出すことができます。
デバッガーの組み込み関数には次の特徴があります。
安全なことが保証されています。デバッガーの組み込み関数を実行しても、デバッグ対象のプロセスは破損しません。
すべての式で使用できます。副作用と関数評価が許可されていないシナリオでも使用できます。
ミニダンプのデバッグ中など、通常の関数呼び出しができないシナリオでも機能します。
デバッガーの組み込み関数は、式の評価をより便利にすることもできます。 たとえば、ブレークポイント条件に記述する際、strncmp(str, “asd”) は str[0] == ‘a’ && str[1] == ‘s’ && str[2] == ‘d’ よりもはるかに簡単です。 )
区分 |
組み込み関数 |
---|---|
文字列長 |
strlen、wcslen、strnlen、wcsnlen |
文字列比較 |
strcmp、wcscmp、stricmp、_stricmp、_strcmpi、wcsicmp、_wcscmpi、_wcsnicmp、strncmp、wcsncmp、strnicmp、wcsnicmp |
文字列検索 |
strchr、wcschr、strstr、wcsstr |
Win32 |
GetLastError()、TlsGetValue() |
Windows 8 |
WindowsGetStringLen()、WindowsGetStringRawBuffer() これらの関数では、デバッグ対象のプロセスが Windows 8 上で動作している必要があります。 Windows 8 デバイスから生成されたダンプ ファイルをデバッグする際も、Visual Studio コンピューターが Windows 8 を実行している必要があります。 ただし、Windows 8 デバイスをリモートでデバッグする場合は、Visual Studio コンピューターが Windows 7 を実行していてもかまいません。 |
その他 |
__log2 指定した整数の底 2 の対数 (最も近い整数に切り捨てられます) を返します。 |
コンテキスト演算子によるシンボルの指定
コンテキスト演算子は、ネイティブなデバッガーによって提供される追加の演算子です。 ネイティブ コードをデバッグするときは、コンテキスト演算子を使ってブレークポイントの場所、変数名、または式を修飾できます。 コンテキスト演算子は、ローカル名で隠されていてほかにアクセス方法がない外部スコープから名前を指定するなどの目的に利用できます。
構文
{,,[module] } expression
module は、モジュールの名前です。 完全パスを使用することで、同じ名前のモジュールのあいまいさを解消することができます。
expression は任意の有効な C++ 式で、module 内の関数名、変数名、ポインター アドレスなどの有効なターゲットに解決します。
中かっこ内には、2 個のコンマとモジュール (実行可能ファイルまたは DLL) 名か完全パスが必要です。
たとえば、EXAMPLE.dll の SomeFunction 関数にブレークポイントを設定する場合は、次のようになります。
{,,EXAMPLE.dll}SomeFunction
module のパスにコンマ、埋め込みスペース、または中かっこが含まれる場合は、コンテキスト パーサーが文字列を適切に認識できるように、パスを引用符で囲む必要があります。 単一引用符は Windows ファイル名の一部として解釈されるので、二重引用符を使用する必要があります。 次に例を示します。
{,"a long, long, library name.dll", } g_Var
式エバリュエーターが式に含まれる記号を見つけると、次の順序で記号を検索します。
構文のスコープの外部。現在のブロック (角かっこで囲まれた一連のステートメント) から、外側のブロックに進みます。 現在のブロックは、現在の場所 (命令ポインター アドレス) を含むコードです。
関数スコープ。 現在の関数です。
クラス スコープ。現在の場所が C++ メンバー関数内部の場合です。 クラス スコープにはすべての基底クラスが含まれます。 式エバリュエーターは、通常の優先順位規則を使用します。
現在のモジュール内のグローバル シンボル。
現在のプログラム内のパブリック シンボル。
コンテキスト演算子を使って、検索開始モジュールを指定したり、現在の場所をバイパスしたりします。
ネイティブ C++ の式の制限事項
デバッガー ウィンドウに C/C++ 式を入力する場合は、次の一般的な制限事項が適用されます。
アクセス制御
デバッガーは、アクセス制御とは無関係にすべてのクラス メンバーにアクセスできます。 基底クラスや埋め込みメンバー オブジェクトなど、任意のクラス オブジェクト メンバーをチェックできます。
あいまいな参照
デバッガー式があいまいなメンバー名を参照する場合は、クラス名を使って修飾する必要があります。 たとえば、CObject が CClass クラスのインスタンスであり、AClass と BClass の両方から expense という名前のメンバー関数を継承する場合、CObject.expense はどちらを指すのかが不明瞭です。 あいまいな参照は、次の方法で解決できます。
CObject.BClass::expense
あいまいな参照を解決するために、式エバリュエーターではメンバー名について通常の優先規則が適用されます。
匿名の名前空間
ネイティブ C++ の式エバリュエーターでは、匿名の名前空間をサポートしていません。 たとえば、次のようなコードがあるとします。
#include "stdafx.h"
namespace mars
{
namespace
{
int test = 0;
}
}
int main()
{
// Adding a watch on test does not work.
mars::test++;
return 0;
}
この例でシンボル test をウォッチするには、装飾名を使用する方法しかありません。
(int*)?test@?A0xccd06570@mars@@3HA
コンストラクター、デストラクター、および変換
暗黙的または明示的にかかわらず、一時オブジェクトを構築するために呼び出す式を使って、オブジェクトのコンストラクターやデストラクターを呼び出すことはできません。 たとえば、次の式は明示的にコンストラクターを呼び出して、エラー メッセージを生じます。
Date( 2, 3, 1985 )
変換先がクラスである場合は、変換関数を呼び出せません。 クラスへの変換には、オブジェクトの構築が必要です。 たとえば、myFraction が CFraction のインスタンスであり、変換関数演算子 FixedPoint を定義する場合、次の式はエラーになります。
(FixedPoint)myFraction
ただし、変換先が組み込み型である場合は、変換関数を呼び出すことができます。 CFraction が変換関数 operator float を定義する場合、デバッガーでは次の式は有効です。
(float)myFraction
オブジェクトを返す関数やローカル オブジェクトを宣言する関数を呼び出すことができます。
new 演算子や delete 演算子を呼び出すことはできません。 デバッガーでは次の式は機能しません。
new Date(2,3,1985)
継承
仮想基底クラスを持つクラス オブジェクトをデバッガーで表示する場合、仮想基底クラスのメンバーのインスタンスが 1 つしか格納されていなくても、メンバーは継承パスごとに表示されます。
仮想関数の呼び出しは、式エバリュエーターによって適切に処理されます。 たとえば、クラス CEmployee が仮想関数 computePay を定義するとします。この関数は CEmployee から継承するクラスに再定義されます。 CEmployee へのポインターを通じて computePay を呼び出して、適切な関数を実行させることができます。
empPtr->computePay()
派生クラス オブジェクトへのポインターを基底クラス オブジェクトへのポインターにキャストできます。 継承が仮想である場合を除いて、基底クラス オブジェクトへのポインターを派生クラス オブジェクトへのポインターにキャストできます。
インライン関数とコンパイラ組み込み関数
デバッガー式でコンパイラ組み込み関数やインライン関数を呼び出すには、その組み込み関数やインライン関数が少なくとも 1 回は通常の関数として現れている必要があります。
数値定数
デバッガー式では、8 進数、10 進数、16 進数の 3 つの形式の整数定数を使用できます。 既定では、10 進数の定数を受け取ります。 この設定は、[デバッグ] タブの [全般] ページで変更できます。
プリフィックス シンボルやサフィックス シンボルを使って、別の基数で数を表すことができます。 使用できる形式を次の表に示します。
構文 |
例 (decimal 100) |
基数 |
---|---|---|
digits |
100 または 64 |
10 進または 16 進 (現在の設定によって変わります)。 |
0 digits |
0144 |
8 進数 (基数 8)。 |
0n digits |
0n100 |
10 進数 (基数 10)。 |
0x digits |
0x64 |
16 進数 (基数 16)。 |
digits h |
64h |
16 進数 (基数 16)。 |
演算子関数
デバッガー式は、クラスの演算子関数を暗黙的にも明示的にも呼び出すことができます。 たとえば、myFraction および yourFraction が、operator+ を定義するクラスのインスタンスであるとします。 これら 2 つのオブジェクトの合計は次の式で表示できます。
myFraction + yourFraction
演算子関数がフレンドとして定義される場合は、メンバー関数と同じ構文で暗黙的に呼び出すことができます。また、次のように明示的に呼び出すこともできます。
operator+( myFraction, yourFraction )
演算子関数は、通常の関数と同様に、オブジェクト構築を伴う変換が必要な引数を指定して呼び出すことはできません。
デバッガーは、定数のバージョンでも非定数のバージョンでも、オーバーロードされた演算子をサポートしません。 const バージョンと非 const バージョンを持つオーバーロードされた演算子は、標準テンプレート ライブラリで頻繁に使用されます。
オーバーロード
完全に一致する関数が存在する場合や、一致条件にオブジェクト構築を伴う変換を必要としない場合、デバッガー式はオーバーロードされた関数を呼び出すことができます。 たとえば、関数 calc が CFraction オブジェクトをパラメーターとして受け取り、CFraction クラスが引数として 1 つの整数を受け付けるコンストラクターを定義している場合、次の式はエラーになります。
calc( 23 )
整数から calc の必要とする CFraction オブジェクトへの変換が有効な場合でも、変換にはオブジェクトの作成が必要であり、この変換はサポートされていません。
優先順位
デバッガー式での C++ のスコープ演算子 (::) は、ソース コード内にあるときよりも優先順位が低くなります。 C++ のソース コードでは、スコープ演算子は最高の優先順位になります。 デバッガーでのスコープ演算子の優先順位は、ベース演算子や後置演算子 (->、++、--) と単項演算子 (!、&、* など) の間になります。
シンボルの書式
完全なデバッグ情報 (/Zi または /ZI) でコンパイルされたモジュールにシンボルが含まれる場合は、ソース コードで使用されるのと同じ形式で、シンボルを含むデバッガー式を入力します。 /Zd でコンパイルされたライブラリやモジュールで使用されるパブリック シンボルを含む式を入力する場合は、シンボルの装飾名 (オブジェクト コードで使用される形式) を使用する必要があります。 詳細については、「/Z7、/Zd、/Zi、/ZI (デバッグ情報の形式)」を参照してください。
LINK /MAP オプションを使用すると、すべての名前のリストを装飾された形式でも装飾されていない形式でも取得できます。 詳細については、「/MAP (マップ ファイルの生成)」を参照してください。
名前の装飾は、タイプ セーフ リンケージを適用するためのしくみです。 つまり、スペル、大文字と小文字、呼び出し規約、および型が正確に一致する名前や参照だけがリンクされることになります。
C 呼び出し規約に従って _cdecl キーワードで暗黙的または明示的に宣言された名前は、先頭にアンダースコア (_) が付きます。 たとえば、関数 main は _main として表示できます。 _fastcall として宣言された名前は、先頭に @ 記号が付きます。
C++ の場合、装飾された名前は、呼び出し規約に加えてシンボルの型をエンコードします。 この名前の形式は長くて読みにくくなることがあります。 名前の先頭には少なくとも 1 つの疑問符 (?) が付きます。 C++ 関数の場合、装飾には関数スコープ、関数のパラメーター型、および関数の戻り値の型が含まれます。
型キャスト
型のキャストを行う場合、その型をデバッガーが認識する必要があります。 プログラム内には、その型の別のオブジェクトが存在する必要があります。 typedef ステートメントで作成された型はサポートされません。