C++Builder 64 ビット Windows アプリケーションのデバッグ
C++Builder 64 ビット Windows アプリケーションの開発 への移動
目次
WIN64 用 C++ LLDB ベース デバッガ
RAD Studio 10.4 では、LLDB をベースとした C++ Win64 用、新しいデバッガが導入されています。このコンパイラは DWARF バージョン 4 形式をデバッグ情報として使用します。
新しい RAD Studio LLDB ベース デバッガでは、デバッグ時の安定性を向上させ、新しいデバッガの技術と生成されたデバッグ情報の両方により、評価、検査、およびその他のデバッガの機能を向上させます。さらに、デバッガは、フォーマッタを介して STL コレクションや文字列などの複雑な型の評価をサポートしています。
フォーマッタ
C++ アプリケーション デバッグ時の一般的な問題は、複雑な型の検査および評価です。たとえば、std::map のコンテンツを評価するには、型のレイアウトの知識が必要であり、配列のアクセス演算子 [] は、それがコード内で呼び出されたことがない場合、もしくは、それが常にインラインであり、呼び出し不可能な場合には、デバッグでは利用できないかもしれません。同様の問題が、文字列など他の型にもあり、また独自の型にもあり得るでしょう。
これは、フォーマッタの利用で解決することができます。フォーマッタは小さな Python スクリプトで、特定の型のデバッグを支援します。RAD Studio は、汎用的な型のフォーマッタを同梱しており、必要に応じてユーザーも自分の型のためのものを追加することができます。
次のフォーマッタは、汎用 STL および Delphi の型のために提供されています。
* std::string and std::wstring * String (UnicodeString), AnsiString, UTF8String, WideString. * std::vector * std::deque * std::stack * std::map * std::shared_ptr
カスタム フォーマッタ
独自のフォーマッタを追加するには、新しい python ファイルを作成し、bin\Windows\lldb\.lldbinit ファイルを編集して、その新しい Python スクリプトを参照する一行を追加します。独自のフォーマッタの記述の情報についてはこちらを参照してください:
- LLDB のフォーマット ドキュメント(英語)
- より良いデバッグ経験を提供するための LLDB の拡張方法(英語)
- カスタム データ フォーマッタの記述に関する Stack Overflow での質問(英語)
- コマンド プロンプト(cmd.exe)を開く
- 入力: set CBUILDER_DBK = 1 そして〔Enter〕を押す
- コマンド プロンプトで bds.exe を起動
C++Builder 64 ビット Windows
C++Builder 64-bit Windows コンパイラ(BCC64)は、デバッグ情報を DWARF 形式で生成します。これは、BCC32 や BCCOSX で使用される形式とは異なります。しかし、一般的に C++ 64 ビット Windows アプリケーションのデバッグは、C++ 32 ビット Windows アプリケーションのデバッグと同等です。違いは次に挙げるものがあります:
- 一部のデバッガ機能がサポートされていません。プロパティ、クロージャ、クラス メソッドなどの Delphi 言語拡張機能のデバッグは現時点ではサポートされていません。
- たとえば、[デバッグ インスペクタ]では、C++ 64 ビット Windows アプリケーションの場合、[メソッド]タブと[プロパティ]タブが表示されません。
- Unicode、コード ページ、ローカライズは、完全にはサポートされていません。
- たとえば、Unicode は識別子名には使用できず、コード ページは C++ 64 ビット Windows 版デバッガではサポートされていません。
- 64 ビット Windows レジスタを評価する際には、
$rax
などのように、レジスタ名の先頭に $ を付ける必要があります。- [評価/変更]を参照してください。
- 例外を送出する関数呼び出しは以下のように処理されます。
- 関数に try/except/catch ブロックが含まれていて、実行中に C++ 例外や OS/SEH 例外が発生した場合、その関数呼び出しは正常に終了しますが、結果は未定義か 0 になります。この場合は、例外がデバッガで直接処理されるため、内部の例外ブロックは実行されません。
- 関数に try/except/catch ブロックが含まれていて、言語例外や OS/SEH 例外が発生しない場合、その関数呼び出しは正常に終了し、結果は関数に応じて正しいものになります。
呼び出し履歴の違い
64 ビット評価モジュールでは、一部の値の表示が 32 ビット評価モジュールの場合とは異なる可能性があります。たとえば、呼び出し履歴の表示には、関数のパラメータと値が含まれません。
呼び出し履歴には、通常、各コンストラクタおよびデストラクタのコピーが 2 つずつ含まれています。 たとえば、呼び出し履歴に以下の内容が含まれているとしましょう。
:0000000000401244 ; MyClass::~MyClass
- :0000000000401229 ; MyClass::~MyClass
- :0000000000401187 ; main
:000000000040ef90 ; _startup
スプリット DWARF によるリンカのメモリ使用量の削減
RAD Studio 10.4.2 では、リンカが処理する(特に、デバッグ モードで構築されたアプリケーションをリンクする際の)データ量の削減を支援する、新しい機能が導入されています。この機能はスプリット DWARF と呼ばれており、デバッグ情報を単独の .dwo ファイル(DWARF オブジェクト)に分割し、コンパイル コードを格納する通常のオブジェクト ファイルと対応させて配置します。その後リンカは、実行可能コードと少量の他の情報のみをリンク付けすることとなり、メモリの負荷が削減されます。
IDE や msbuild でスプリット DWARF を有効にする
C++ プロジェクト オプションのダイアログを開きます。[ビルド|C++ コンパイラ|デバッガ]と移動し、ターゲット プラットフォームが Windows 64 ビット ターゲットのいずれかに設定されていることを確認します。
- [Split DWARF を使用]チェックボックスをオンにします。
- デバッグ情報ファイル用のフォルダを設定の[DWO 出力ディレクトリ]に指定します。これは相対パスや環境変数を使用したパスではなく、絶対パスでなければなりません。
たとえば、c:\myproject\win64debug は OK ですが、..\win64debug は使用できません。
この機能を無効にするには、[プロジェクト オプション|ビルド|C++ コンパイラ|デバッグ]のチェックボックスのチェックを外します。これらの設定は、IDE 内からビルドする、またはコマンドライン上で msbuild でビルドする際に使用されるものです。
スプリット DWARF をコマンドラインで有効にする
BCC64 を使用するように、純粋なコマンドライン ビルドで、スプリット DWARFを手動で有効にするには:
1. スプリット DWARF の設定を、コンパイラのコマンドラインで指定します。
"-enable-split-dwarf" AND "-split-dwarf-file AFilename.dwo"
これにより、
コンパイラは AFilename.dwo ファイルを作成し、その .dwo ファイルの場所を .o オブジェクト ファイルに出力します。このステップではまだ、.dwo ファイルにデバッグ情報が格納されたことにはなりません。
2. "-dwo-dir <ディレクトリ>" を使用して、コンパイラが .dwo ファイルを書きだすディレクトリを指定します。これは、絶対パスでなければなりません。
3. objcopy.exe ツールを .o ファイルに対して実行します。このアクションでは、すべての dwarf セクションを、通常のオブジェクト (.o) ファイルから削除し、それらを別の .dwo ファイルに配置します。これは、各オブジェクト (.o) ファイルに対して必要で、ステップ 1 で指定した名前を一致する必要があります。
objcopy --split-dwo=AFilename.dwo AFilename.o
4. 最後に、.o ファイルをリンクして、通常の同じように、EXE または DLL を作成します - このステップは変わりません。このファイルは通常よりも小さくなり、その中のデバッグ情報は少なくなっています。各オブジェクトは、.dwo の名前を場所を格納するようになります。ステップ 2 のように、これはお使いのマシンの場所であり、絶対パスで指定されなければなりません。
スプリット DWARF 使用時のデバッグ情報の読み込みの問題
Split-Dwarf for Win64 デバッグの使用時、プロジェクト ファイルと同じディレクトリにないソース ファイルは、誤ったディレクトリ情報がオブジェクト ファイルに生成されてしまう場合があります。これは、それらのファイルからのシンボル(型、ローカル変数、パラメータ)が利用できないことを意味します。この状態は、デバッグ時、行番号を示すエディタ上で青色の点が表示され、そこにブレークポイントを配置することができますが、式やシンボルを評価または検査することができないことで認識できるでしょう。
これを回避するには、[C++ コンパイラ|デバッグ|Split DWARF を使用]プロジェクト オプションの[DWO 出力ディレクトリ]フィールドに、もしくは、コマンドラインでビルドする際には -dwo-dir コマンドライン オプションで、絶対パスを指定することです。これらの設定については、上記を参照してください。
strcmp() などの関数呼び出しの評価
strcmp(str, "ABC") などの関数呼び出しを評価すると、以下のようなエラーが返されるおそれがあります。
#include <system.hpp> int main() { char *str = "ABC"; return strcmp(str, "ABC"); } error: 'strcmp' has unknown return type; cast the call to its declared return type error: 1 errors parsing expression
[評価/変更]ウィンドウでは、strcmp() の戻り値型をキャストする必要があります。
(int) strcmp(str, "ABC");
詳細については、「strcmp、_mbscmp、wcscmp」を参照してください。