C++Builder 2009 ファーストガイド 第五回「プログラミング手順(後編)」

By: Kenji Umeda

Abstract: C++Builder 2009のプログラミング手順(後編)の説明です。

このファーストガイドは、これから C++Builder 2009を使い始める初心者の方を対象に 10回に分けて基本的事項を説明していきます。

blank

第五回は、プログラミング手順の後編としまして、アプリケーションを構築する上で必要不可欠なプログラムのテストに関する項目を中心に説明していきます。

blank

C++Builderが提供するビジュアルコンポーネントは、それ自体が動作テスト済みで、かつ再利用可能なクラスなため、ビジュアルデザイナの機能を使ってフォーム画面を設計し、わずかなコーディング量でアプリケーションを作成することもできますが、実際のアプリケーション開発では、このように簡単にはいきません。

アプリケーションの用途や目的に合わせた独自のビジネスロジックを実装したり、コンポーネントの足りない機能を補う必然性も出てくるでしょう。そのためプログラムコードの実装を行った部分も含めて、仕様通りに正しく動作するか十分なテストを行うことが大切です。そのためにはデバッグが必要になります。

また実際のアプリケーション開発における実装フェーズでは、プログラムを記述している時間よりも、デバッグしている時間のほうが長いというケースも珍しくないと思います。

このようにアプリケーション開発において非常に大きなウェイトを占めるデバッグの作業をいかに効率よく行えるか、それがアプリケーションの品質、そして開発の生産性を向上させる重要な要素となります。

blank

C++Builderでは、「統合デバッガ」と呼ばれるソースコードレベルでプログラムのデバッグが行える機能を備えています。

このデバッガは、統合開発環境から簡単に利用することができ、プログラムの内部の動作を確認する上で必要な多くの情報を様々な機能によって開発者に提供してくれます。

本章では、プログラムのテスト手順として、コンパイルエラーの解決、そしてデバッグについて詳しく見ていきたいと思います。

blank

    プログラムのテスト手順

プログラミング手順の前編では、「プロジェクトの作成」から「プログラムの実行」までの手順を通し、簡単なアプリケーションの作成方法を説明しました。

しかしながら前編では作成したアプリケーションが正常に動作することを前提に話を進めていたため、プログラムテストに関しては特に触れていませんでした。

実際のアプリケーション作成の手順では、プログラムが正しく動作するか評価を行うテスト作業が含まれ、開発手順の中でも特に重要な意味を持ちます。

一般的にテスト手順は、テスト(プログラムの不具合の検出)→デバッグ(プログラムの不具合の修正)の繰り返しで行われます。

blank

最近のアプリケーション開発では、実装コードを書く前にテストコードを書き、それらの逐次テストを行う「テストファースト(ユニットテスト)という考え方が主流です。

テストコードとは、それ自身がテストケース(仕様)と見なし、そのコードを見れば、テスト対象のクラスやメソッドの振る舞い、使い方を知ることができます。

テストファーストにおけるテスト手順は、テストケース作成 → 実装 → テスト実施という流れになります。

C++Builderでは、テストファーストの手法もサポートしていますが、本章では特に触れません。

本章では、一般的なテスト手順である、不具合を検出し、その原因を調べ、そしてプログラムコードを修正していく「実装 → テスト実施」という流れで説明していきます。

前編のプログラミング手順にテスト作業を加えると、C++Builderの開発手順は以下のようになります。

blank

1.プロジェクトの作成

2.コンポーネントの配置

3.プロパティの設定

4.イベントハンドラの設定

5.プロジェクトのメイク

6.コンパイルエラーが見つかれば修正し、手順5に戻る

7.プログラムの実行、テスト

8.プログラムのデバッグを行い、エラー見つかれば修正し、手順5に戻る

blank

プログラミング手順の後編では、ステップ5からステップ8の手順を中心に説明していきます。

プログラムを実装する過程で開発者が遭遇するエラーとして以下の項目があります。

・コンパイルエラー

・実行時エラー、論理エラー

blank

次節以降で、それぞれのエラーを解決するためC++Builderが持つ機能の説明と簡単な対処例を交えて見ていきたいと思います。

blank

    テストを行うための前準備

今回のテストを行うために、以下の手順で簡単なVCLフォームアプリケーションを作成してみましょう。

blank

(1)メニューバーの[ファイル]-[新規作成]から[VCLフォームアプリケーション]を選択し、新規プロジェクトを作成します。

(2)ツールパレットからTButtonコンポーネントとTEditコンポーネントを選択し、フォーム上へ配置します。

(3)オブジェクトインスペクタで、Button1のCaptionプロパティを”Button1”から”メッセージの表示”へ変更します。

(4)フォーム上のボタン(Button1)をダブルクリックして、イベントハンドラを作成します。

(5)Button1のonClickイベントハンドラ内に以下のようなコードを追加します。

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  char *Buff=new char[Edit1->Text.Length()+1];
  strcpy(Buff,Edit1->Text.c_str());
  ShowMessage(Buff);
}

(6)プロジェクトを保存します。

(7)メニューバーの[プロジェクト]-[プロジェクトのメイク]もしくは、ショートカットキーの[Ctrl+F9]を実行し、プログラムコードをコンパイルします。

blank

ステップ7を実行すると、コンパイルエラーが発生します。

blank

    コンパイルエラー

プログラムの記述に間違いがあるとコンパイルエラーが発生します。C++Builderでは、コンパイルエラーが発生すると、コードエディタの下にメッセージウインドウが表示され、エラーを検出したソースコードが赤く反転表示されます。

=> 1(1)を参照

Hide image
Click to see full-sized image

図1: コンパイルエラーの表示

expand view>>

blank

メッセージウインドウにはエラーが発生したソースファイル名、ソースコードの行数、エラーコード、そしてエラーメッセージなどが表示されます。

=> 1(2)を参照

blank

    警告オプションの設定

メッセージウインドウに表示されるメッセージには、[エラー]や[警告]など、いくつかの種類があります。

=> 1(3)を参照

このうち[エラー]の場合には、コンパイルは正常に完了せず、プログラムファイルは作成されませんが、

[警告]の場合は、プログラムファイルが作成されます。警告は無視しても構わないことが多いのですが、中にはプログラム実行時に問題になるケースもあるため、メッセージの意味を把握し、本当に無視しても構わないかチェックする必要があります。

C++Builderでは、コンパイル時の警告に対する設定をプロジェクトオプションで細かく指定できます。

プロジェクトオプションの設定は、メニューバーの[プロジェクト]-[オプション]-[C++コンパイラ]-[警告]で行います。

Hide image
Click to see full-sized image

2: [警告]に関する設定

expand view>>

blank

    エラーコードの詳細情報

メッセージウインドウに表示されているエラー項目を選択することができ、選択された項目は、青く反転表示されます。

=> 3を参照

Hide image
Message

3: エラー項目の選択

blank

エラーメッセージを選択(青く反転表示)した状態で、 [F1]キーを押すと図4のようにドキュメントヘルプが自動的に起動し、エラーコードに該当するエラーメッセージの詳細な内容が表示されます。

ただし、C++Builder2009のドキュメントヘルプを予めインストールしておく必要があります。詳しくはこちらを参照ください。

Hide image
Click to see full-sized image

4: エラーコードの詳細な情報の表示

expand view>>

blank

    コンパイルエラーの対処例

それでは、図1で発生していたコンパイルエラーを実際に修正してみましょう。

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  char *Buff=new char[Edit1->Text.Length()+1];
  strcpy(Buff,Edit1->Text.c_str()); <======(1)
  ShowMessage(Buff);
}

5: ボタンのクリックイベントのコード

上記のコードは、フォーム上にボタン(Button1)とエディットボックス(Edit1)が配置されており、Button1のクリックイベントが発生すると、new演算子によってEdit1に入力されている文字数分の動的配列(Buff)がローカルに確保されます。そしてEdit1に入力されている文字列がBuffポインタへコピーされ、最後にメッセージボックスによってBuffポインタの内容が表示されるというプログラムの断片コードです。

blank

そしてコンパイルを行うと、図5の(1)に相当するソース行で、以下のようなコンパイルエラーが発生しています。

[BCC32 エラー] Unit1.cpp(21): E2034 'wchar_t *' 型は 'const char *' 型に変換できない
[BCC32 エラー] Unit1.cpp(21): E2342 パラメータ '__src' は const char * 型として定義されているので wchar_t * は渡せない

上記のエラーは、メッセージの内容を見る限りでは、strcpy関数のコピー元とコピー先の引数の型が不一致であることが原因のようです。

但し、このプログラムはC++Builder2007までは同じコードでコンパイルエラーは発生しませんでした。

さて、C++Builder2007とC++Builder2009では、どこが変わっているのでしょうか。

その違いを調べるには、ライブラリリファレンスで、使い方を調べたほうが解決は早そうです。

Hide image
Click to see full-sized image

6: コードエディタ内でカーソル位置合わせる

expand view>>

blank

C++Builderでは、図6のようにコードエディタ内でカーソル位置を特定のクラスや関数の上に合わせて[F1]キーを押すと、ドキュメントヘルプが起動します。

そして該当するリファレンスのトピックが複数見つかると、図7のようなダイアログが表示されます。

Hide image
無題4

7: 複数のトピックの選択ダイアログ

blank

ここでは、”UnicodeString::c_strメソッド”を選択します。すると、図8のように選択したメソッドのリファレンスが表示されます。

Hide image
Click to see full-sized image

8: ライブラリリファレンスの表示(ドキュメントヘルプ)

expand view>>

blank

このショートカットキーからドキュメントヘルプを呼び出す機能は、クラスや関数の説明や仕様を調べたいときに非常に便利です。

C++Builder2009からデフォルトで扱う文字列型は、AnsiString型からUnicodeString型へ置き換わっています。

例えば、EditコンポーネントのTextプロパティや、ButtonコンポーネントのCaptionプロパティなど内部的に扱う文字列型は全てUnicodeString型に置き換わっています。

そのため文字列型のポインタを返すc_strメソッドの仕様もC++Builder2009では変更されているわけです。

(c_strメソッドが返すポインタ型は、char* から wchar_t*に変更されています)

blank

C++Builder2009で、新しくサポートされた文字列型(UnicodeString)については、第6回以降で取り上げます。

ここでは、デフォルトで扱う文字列型が変わったことにより、c_strメソッドが返すポインタ型も変更されたことだけ理解してください。

コンパイルエラーに対処するには、以下の2つの方法があります。

1.AnsiString型へ明示的にキャストする方法

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  char *Buff=new char[Edit1->Text.Length()+1];
  strcpy(Buff,AnsiString(Edit1->Text).c_str());
  ShowMessage(Buff);
}

AnsiString型へ明示的にキャストすることで、C/C++言語の従来の1バイト文字型(char型)との互換を保つことができます。

但し、この方法ではUnicode文字は表示することはできません。

blank

2.ワイド文字(2バイト)対応の文字型や関数を利用する方法

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  wchar_t *Buff=new wchar_t[Edit1->Text.Length()+1];
  wcscpy(Buff,Edit1->Text.c_str());
  ShowMessage(Buff);
}

UnicodeString型は、1文字あたりのサイズが2バイトになります。そのためC/C++言語で扱うchar型では互換が無く、Unicode対応のwchar_t型を利用する必要があります。また文字列を扱う関数も従来の1バイト文字対応(str~)のものではなく、Unicodeに対応した文字列関数(wcs~)を利用する必要があります。

例えば、文字列をコピーする関数は、strcpyからwcscpy関数へ変更します。

ここでは、2.の方法でプログラムを修正します。修正後のUnit1.cppのソースコードは以下の通りです。

Hide image
Click to see full-sized image

9: 修正後のUnit1.cppのソースコード

expand view>>

blank

修正した後、プロジェクトのメイクを実行すると、コンパイルが正常に完了します。

Hide image
無題

10: コンパイルが完了

blank

    統合デバッガ

コンパイルエラーが解決できたとしてもプログラムが正しく動作するとは限りません。コンパイルエラーは、あくまでも文法上のミスを検出しているだけで、プログラムの動作自体はチェックできません。例えば、あるコードで、1を加算すべきところを誤って1を減算してもコンパイラはそれが間違っていることに気がつきません。

またプログラムの実行後、存在しないファイルやデータベースなどのリソースにアクセスしようとしたり、0除算を行った場合などに発生する「実行時エラー」や、プログラム自体は正常に起動しますが、プログラムが期待した動作や意図した結果を出力しないような「論理エラー」などは、実行時に検出されることが多いため、プログラムを実行してみないとその結果が分かりません。

C++Builderには、ソースコードレベルでエラーの原因を追及するための統合デバッガを用意されており、

デバッガを利用することによって、プログラムの実行時エラーや論理エラーの原因を究明することができます。

プログラムのデバッグを行うためにはデバッグセッションを開始します。デバッグセッションの開始により、デバッガの元でプログラムが実行され、プログラムの停止、そして変数の値の確認/変更などが行えます。

blank

デバッグセッションの開始は、メニューバーの[実行]-[実行]を選択するか、ショートカットキーの[F9]を押します。デバッグセッションを開始すると統合開発環境のレイアウトが切り替わります。

C++Builderでは、このレイアウトをデバッグレイアウトと呼びます。図8は、デフォルトのデバッグレイアウトです。

Hide image
Click to see full-sized image

11: デフォルトのデバッグレイアウト

expand view>>

blank

デバッグ時に使用可能なウインドウは、主に以下の通りです。

・イベントログ           => 図11(1)

・ローカル変数           => 図11の(2)

・監視式      => 図11の(3)

・呼び出し履歴           => 図11の(4)

・CPUウインドウ

・モジュール

blank

以降の節で、デバッガ機能が持つ各ウインドウの役割について説明します。

blank

    イベントログ

イベントログウインドウは、プロセス制御メッセージ、ブレークポイントのメッセージ、OutputDebugStringsメッセージ、ウインドウメッセージなどを表示します。

このウインドウは、デフォルトのデバッグレイアウトでは表示されていますが、メニューバーの[表示]-[デバッグ]-[イベントログ]、もしくはショートカットキーの[Ctrl+Alt+V]でも表示できます。

Hide image
Click to see full-sized image

12: イベントログウインドウ

expand view>>

blank

イベントログは、ウインドウ内でマウスボタンを右クリックすると、ログをクリアしたり、イベントログのオプション設定ができ、表示するメッセージの種類やイベント数などをカスタマイズできます。

Hide image
Click to see full-sized image

13: イベントログのオプション設定

expand view>>

blank

    ローカル変数

ローカル変数をモニタするには、ローカル変数ウインドウを使用します。このウインドウは、デフォルトのデバッグレイアウトでは表示されていますが、メニューバーの[表示]-[デバッグ]-[ローカル変数]、もしくはショートカットキーの[Ctrl+Alt+L]でも表示できます。

Hide image
無題

14: ローカル変数ウインドウ

blank

ローカル変数ウインドウには、プログラムが一時停止した状態でモニタできる変数の内容が表示されます。モニタされた変数の内容は、プログラムのステップ実行によりその内容が即座に変わります。

例えば、for やwhileなどのループ処理内をステップ実行した場合には、その中で使用している変数、ループカウンタ全てをモニタでき、どのように変数の値が変化していったかを確認することができます。

Hide image
Click to see full-sized image

15: 変数の内容の表示結果

expand view>>

blank

図15では、ローカル変数のsumとiが表示される他、イベントハンドラの引数(Sender)や変数thisが表示されています。ローカル変数ウインドウでは、単に変数の値を見ることができるだけで無く、ウインドウ内に表示された変数を任意の値に書き換えることもできます。

Hide image
Click to see full-sized image

expand view>>

16: デバッグインスペクタ

blank

表示された変数の内容を書き換える場合には、ウインドウ内の変数を選択してダブルクリックすると、選択した変数に対するデバッグインスペクタが表示されます。

=> 16(1)を参照

さらにデバックインスペクタ内の変数に対応した[…]ボタンをクリックすると、変更ダイアログが表示されます。

=> 16(2)を参照

そして、変更ダイアログで選択した変数を任意の値に書き換えることができます。

blank

    監視式

プログラムを実行中に変化する変数や式の値を監視するには、監視式を使用します。このウインドウは、デフォルトのデバッグレイアウトでは表示されていますが、メニューバーの[表示]-[デバッグ]-[監視式]、もしくはショートカットキーの[Ctrl+Alt+W]でも表示できます。

Hide image
無題

17: [監視式]ウインドウ

blank

項目

説明

監視式

監視として入力した式が表示されます。

入力した式の現在値をリストします。

実行ポイントで監視式が未定義(スコープ外)の場合、値は”E2451未定義のシンボル”と表示されます。

blank

監視式を追加するには、ウインドウ内でマウスボタンを左クリックして[監視式の追加]を選択、または[実行]-[監視式追加]、もしくはショートカットキー[Ctrl+F5]を押すと、[監視式のプロパティ]ダイアログボックスが表示され、そのメニューから行ないます。

Hide image
無題

18: [監視式のプロパティ]ダイアログボックス

blank

このダイアログボックスでは、[監視する式]編集ボックスに監視する変数や式を入力し、繰り返し回数には監視式が配列を表すときの配列の要素数を指定します。

ダイアログボックスの下にあるラジオボタンは、監視式の結果をどのような形式で表示するかを選択する場合に使用します。

デフォルトは式のデータ型に一致した形式で表示し、数値の場合には10進数で表示します。デフォルト以外の形式で表示したい場合に任意のラジオボタンを変更します。

blank

    呼び出し履歴

呼び出し履歴ウインドウは、現在のプログラムの位置まで移動した関数呼び出し、及び各関数呼び出しに渡された引数が表示されます。

Hide image
Click to see full-sized image

19: 呼び出し履歴ウインドウ

expand view>>

blank

呼び出し履歴ウインドウは、デフォルトのデバッグレイアウトでは表示されていますが、メニューバーの[表示]-[デバッグ]-[呼び出し履歴] 、もしくはショートカットキーの[Ctrl+Alt+S]でも表示できます。

関数に対応したデバッグ情報がある場合は、呼び出し時に渡された引数に続いてデバッグ情報が表示されます。

またウインドウ内でマウスボタンを右クリックすると、ソースの表示やローカル変数の表示、そしてプレークポイントを設定できます。

blank

    CPUウインドウ

CPUウインドウは、アセンブルレベルでデバッグを行うときに使用します。

このウインドウは、メニューバーの[表示]-[デバッグ]-[CPUウインドウ]-[CPU全体]、もしくはショートカットキーの[Ctrl+Alt+C]でも表示できます。それ以外にもスタック、レジスタ、メモリといった単位でウインドウを表示することもできます。

Hide image
Click to see full-sized image

20: CPUウインドウ(CPU全体)

expand view>>

blank

CPUウインドウは、5つのペインから構成され、それぞれ次の情報が表示されます。

ペイン

内容

(1)逆アセンブル

アプリケーションの機械語コードから逆アセンブルされたアセンブリ命令が表示されます。

(2)ダンプペイン

現在ロードされている実行可能モジュールからアクセス可能なメモリダンプが表示されます。

(3)レジスタペイン

CPUレジスタの現在の値が表示されます。

(4)フラグペイン

CPUフラグの現在の値が表示されます。

(5)スタックペイン

プログラムスタックの内容が16進数(32ビット)で表示されます。

blank

    モジュール

モジュールウインドウは、デバッグ中のアプリケーションで読み込んだモジュールについての情報を表示します。

Hide image
Click to see full-sized image

21: モジュールウインドウ

expand view>>

blank

モジュールウインドウは、メニューバーの[表示]-[デバッグ]-[モジュール]、もしくはショートカットキーの[Ctrl+Alt+M]で表示されます。

このウインドウでは、読み込まれたモジュールファイル名とアドレスが表示され、任意のモジュール名を選択するとそのエントリポイント名とアドレスが表示されます。

blank

以上がデバッガ機能の持つ各ウインドウの役割の説明でした。これらの機能を活用することでプログラムの内部の動作を確認でき、効率良くプログラムのデバッグが行えます。

各ウインドウの役割が理解できたところで、次節ではデバッガを使ったプログラム実行の制御方法について見ていきましょう。

blank

    プログラム実行の制御

プログラムに任意の停止ポイントを設定して実行し、プログラムを停止しながら問題のある箇所を集中的にデバッグすることはよく行われます。C++Builderでは、ソースコードに停止ポイント(ブレークポイント)を設定し、1ステップごとに実行していくことができます。ステップ実行以外にもさまざまなデバッグ実行が行えますが、ここでは基本的な制御方法を説明します。

制御方法

機能

ブレークポイントまでの実行

ソースコードに停止点(ブレークポイント)を設定しておくと、その場所に来た時にプログラムが一旦停止します。

ステップ実行

一旦停止状態から、1ステップずつプログラムを実行していきます。

メニューバーの[実行]-[ステップ実行]を選択、もしくはショートカットキーの[F8]を押します。

カーソル位置までの実行

ブレークポイントに似ていますが、ブレークポイントを設定せずに、現在のカーソルの位置まで来ると一旦停止します。メニューバーの[実行]-[カーソル位置まで実行]を選択、もしくはショートカットキーの[F4]を押します。

実行の一時停止

実行中のプログラムをメニューバーの[実行]-[プログラムの停止]により、一時停止することができます。

実行の終了

実行中のプログラムを終了するには、メニューバーの[実行]-[プログラムの終了]を選択、もしくはショートカットキーの[Ctrl+F2]を押すことで、実行中のプログラムが終了し、同時にデバッグセッションも終了します。

blank

    ブレークポイント

特定の行でプログラムの一時停止をするには、ブレークポイントを設定します。

Hide image
Click to see full-sized image

22: ブレークポイント

expand view>>

blank

ブレークポイントを設定するには、コードエディタの任意のソース位置でショーカットキーの[F5]を押すか、左端をクリックすると、図22のように設定した行が青色の反転表示に変わります。

ブレークポイントを解除するには、設定した行でもう一度[F5]キーを押すか、図22のコードエディタの左側に表示されている赤色のトグルをクリックします。

ブレークポイントは、複数個設定することができます。そしてブレークポイントの情報は、メニューバーの[表示]-[デバッグ]-[ブレークポイント]、もしくはショートカットキーの[Ctrl+Alt+B]を押すと、ブレークポイントの一覧が表示されます。このウインドウでは、複数のブレークポイントの管理が行えます。

Hide image
Click to see full-sized image

23: ブレークポイントの一覧

expand view>>

blank

またそれぞれのブレークポイントに対して、ブレーク条件などを指定することができます。

Hide image
Click to see full-sized image

24: ソースコードブレークポイントの設定ダイアログ

expand view>>

blank

図24のように一覧からブレークポイントを選択し、マウスの右ボタンをクリックし、[プロパティ]を選択します。ソースコードブレークポイントの設定ダイアログが表示されます。

[ブレーク条件]には、ブレークポイントに対する停止条件を記述することができ、ブレークポイントに達する度に評価される条件式を指定します。そして式の評価値がtrueの場合、プログラムが停止します。

blank

    デバッグ実行の例

それでは図9で修正、そしてコンパイル済みのアプリケーションを使用し、OnClickイベントハンドラで実装したコードのデバッグを行ってみましょう。

またブレークポイントの設定やステップ実行の方法、そしてローカル変数の内容を確認してみましょう。

    1.ブレークポイントを設定する

コードエディタでUnit1.cppを開き、図25のようなソース位置でブレークポイントを設定します。

ブレークポイントの設定は、該当する行で左端をクリックするか、ショートカットキーの[F5]を押します。

Hide image
Click to see full-sized image

25: ブレークポイントの設定

expand view>>

blank

    2.デバッグセッションの開始

ブレークポイントの設定が完了したら、プログラムを実行します。

メニューバーの[実行]-[実行]を選択するか、ショートカットキーの[F9]を押すと、デバッグセッションが開始されます。

Hide image
無題2

26: プログラム実行直後のフォーム画面

blank

    3.エディットボックスに文字列を入力し、ボタンを押す

エディットボックス内のデフォルトの文字列は、「Edit1」になっていますので、何か別の文字列を入力します。

C++Builder2009では、Unicodeに対応していますので、入力する文字列の中にUnicode文字が含まれていても正しく表示されます。

ここでは、”あいうえお”と入力します。

Hide image
無題3

27: エディットボックスへ文字の入力

blank

そして“メッセージの表示”と表示されたボタンを押します。

blank

    4.ブレークポイントで停止

ボタンを押すと、図28のようにブレークポイントを設定した位置で、プログラムが一時停止します。

カーソルはコードエディタ内の一時停止したプログラムのソース行を指し、イベントログには、ブレークポイントで停止した位置が赤色で反転表示されます。

Hide image
Click to see full-sized image

28: ブレークポイントで停止

expand view>>

blank

    5.ステップ実行

それでは、ブレークポイントで一時停止した位置から1ステップずつ実行し、ローカル変数の内容を確認していきましょう。ステップ実行するには、メニューバーの[実行]-[ステップ実行]を選択するか、ショットカットキーの[F8]を押します。

ステップ実行すると、図29のように現在実行されているソース位置が赤色に反転表示され、カーソルが進みます。

Hide image
Click to see full-sized image

29: ステップ実行(その1)

expand view>>

blank

またローカル変数ウインドウで表示されている項目を見てみると、Buff変数がnew演算子によって配列が確保されたので、割り当てられた配列の先頭アドレスが表示されています。

(アドレス:00B40960)

ただし、カーソルが指すステップでは、配列の確保が行われただけで、文字列の中身はまだ初期化されていません。

それでは、さらにもう1つステップを実行してみましょう。[F8]キーを押して下さい。

blank

図30のようにカーソルの位置がまた1行進みました。それに伴って文字列のコピー関数が実行されたため、ローカル変数ウインドウのBuff変数の値が変更されています。Edit1のTextプロパティの内容がコピーされていることがわかります。

Hide image
Click to see full-sized image

30: ステップ実行(その2)

expand view>>

blank

また変数値の表示は、ローカル変数ウインドウ以外で確認する方法もあります。コードエディタ内で任意の変数の上にカーソルを合わせます。

例えば、図31 (1)のようにBuffの上にカーソルを合わせると、その変数に対する現在実行されている位置までの値がツールチップとして表示されます。

ローカル変数ウインドウで表示されている内容と同じ値であることがわかります。

Hide image
Click to see full-sized image

31: ローカル変数のツールチップ表示

expand view>>

blank

    6.メッセージボックスの表示

さらにステップ実行すると、ShowMessage部分のコードが実行され、onClickイベントハンドラの処理が終了します。

Hide image
Click to see full-sized image

32: メッセージボックスの表示

expand view>>

blank

そして、メッセージボックスにエディットボックスに入力した文字列が表示されます。

blank

    7.デバッグセッションの終了

デバッグセッションを終了させるには、メニューバーの[実行]-[プログラムの終了]を選択するか、ショートカットキーの[Ctrl+F2]を押します。

Hide image
無題

33: プログラムの終了

blank

実は、このプログラムでは、イベントハンドラ内でnew演算子によって動的にメモリ確保した配列をdeleteしていないため、メモリリークが発生します。

C++Builderでは、上記の問題を簡単に調査が行える「CodeGuard」という機能が用意されています。

blank

    CodeGuard

CodeGuardは、実行時にランタイムライブラリを追跡し、メモリリークやリソースリーク、そしてバッファオーバーランといった問題を検出し、エラーとして報告する機能を持っています。

CodeGuardの機能を有効にするには、メニューバーの[プロジェクト]-[プロジェクトオプション]-[C++コンパイラ]-[デバッグ]の項目で、[CodeGuardを有効にする]の設定をFalseからTrueに変更します。(このオプションのデフォルトはFalseです。)

Hide image
無題

34: CodeGuardの有効化

blank

このオプションを有効にし、プログラムを実行します。

そしてプログラム実行時、CodeGuardによってエラーが検出された場合は、プログラム終了時にその詳細が報告されます。

Hide image
Click to see full-sized image

35: CodeGuardによる報告

expand view>>

blank

CodeGuardは、図35のようにUnit1.cppの19行目で動的確保した配列の削除(delete)を行っていないと報告しています。

メモリリークを解消するためには、以下のようにコードを修正する必要があります。

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  wchar_t *Buff=new wchar_t[Edit1->Text.Length()+1];
  wcscpy(Buff,Edit1->Text.c_str());
  ShowMessage(Buff);
 delete[] Buff;
}

blank

CodeGuardには、今回紹介したケース以外にも様々なエラーを報告してくれる機能を持っていますが、CodeGuardの詳しい使い方につきましては、また別の機会で紹介したいと思います。

blank

    まとめ

本章では、ローカル変数の内容を確認する手順のみで、C++Builderが持つ他のデバッグ機能を扱った手順は紹介しませんでしたが、統合デバッガの機能を活用し、アプリケーションのデバッグ時における様々な状態をウォッチすることで、コードレベルでは判明しない不具合も検出が行えます。

blank

    あとがき

第五回は 、プログラミング手順の後編としまして作成したプログラムコードに対する「コンパイルエラーの解決」や「デバッグ」といったトピックを中心にC++Builderが持つ統合デバッガの機能を説明しました。

第六回は、「C++の基礎知識編」です。C++Builderでプログラミングを行なう上で、必要なC++言語の基礎事項を説明する予定です。

Server Response from: ETNASC03