デバッキング1

デバッグの使い方

デバッグの原文の場所は、
ヘルプ-->ヘルプトピック-->UserGuide画面
UserInterface-->ToolBox-->Dbug
になります。

「デバック」タブは、このプロセスが動いているときのみ、
表示します。
ウインドウは2つに別れています。
左側の部分はコールスタックを表示し、
右側の部分は観察する式の値を表示します。

コールスタック
コールスタックは次のようなテーブル形式で表示されます。
1、ファイル
関数から呼ばれたファイルの名前とパス。
2、関数
実行プログラムの現ステージの関数の名前。
3、ライン
実行プログラムがストップしたライン番号。

トグルで止まるブレークポイントがなく、
実行するステップバイステップのコマンドがないとき、
ウインドウの左側の部分は空のままです。

コンテントメニューコマンドを使い、
フィールドを分けているグリッドを表示/非表示に出来ます。
さらに、コラムの自動整列を可能/無効にできます。

式の観察
デバックウインドウの右側の部分は、
デバック処理中の式の値の観察を行います。
次のようなフィールドの情報を表示します。


観察している式の名前。


観察している式の値。

タイプ
式のタイプ

式の値が定義されていないか、
まだ計算されていないときは、
"Unknown identifier" (未知な識別子)の表示が、
関連するフィールドに表示されます。
そのような式は、アイコン(!)の目印が付きます。
ウインドウで表示する式を表示するため、
ソースコードのウオーキングウインドウのコンテンツメニューで、
「アドウオッチ」(めがねのアイコン)をクリックします。

コンテックスメニュー
ウインドウ右側のコンテックスメニューは1つのコマンドを実行します。
•Edit (編集)
観察する式の編集、
式の名前フィールドでダブルクリックするか、
F2キーを押すことで同じアクションが動作します。

Add(アドウオッチ)
式を加えます。このボタンを押すと、新しいラインがテーブルに表示されます。
式のフィールドでは、観察する式の名前を入力します。
インサートキーを押すことで、式を加えることが出来ます。

Delete
選択した式を削除します。
同にアクションが「Delete」キーを押す事で出来ます。

値のコピー
クリップボードに式の値をコピーします。

グリッド
フィールドを分けているグリッドの表示/非表示。
同じアクションが「G」キーを押す事で出来ます。

自動整列
コラムの自動整列を可能/無効にします。
同じアクションが「A」キーを押す事で出来ます。
-----
デッバギングのやり方

デッバギングの原文の場所は、
ヘルプ-->ヘルプトピック-->UserGuide画面
Creating Program-->Debugging
になります。

Debugging

難しいプログラム書いているとき、
エラーを除去するのはハードな仕事です。
問題を解決する補助のため、
メタエディターはビルトインデバッカーを提供しています。
アプリケーションのデバッギングは、
ステップバイステップのプログラム実行を可能にし、
プレゼンテーション位置のブレークポイントをセットし、
ローカル変数の計算をします。
デバッギングをスタートするには、
プロジェクトのメインファイルをアクティブしなければなりません。
含まれているファイルはデバックのためスタートします。


さらにデバッグ処理の詳細を記述します。

Presetting
プログラムのデバッギングをスタートさせる前に
メタエディターのオプションウインドウ・デバッギングタブで、
パラメータをチェックする必要があります。
このウインドウで、
シンボルとチャート足の設定を、
アプリケーションのデバッギングに反映させます。
デバッギングがスタートすると、
チャートが各々テンポラリーに生成され、
デバッギングが終了すると削除されます。

クライアント端末の/profiles/templatesフォルダーに
「debug.tpl」テンプレートがあり、
デバッギングの為生成されたチャートへ適用されます。

Breakpoints
ブレークポイントは、プログラムの実行開始後、
指示されたラインでトリガーし、
その場所でストップするコマンドです。
ブレークポイントでは、
選択された箇所でプログラムの振る舞いを解析します。
すなわち、変数の値を見、関数をスタックします。
その後、さらにデバッギング処理は続けられ、完了します。

デバッギングの前に、必要なコード位置にブレークポイント設定します。
それをする為には、
コード行の左側ボーダの近くのグレーフィールドで、
マウス左ボタンを2回クリックします。
または、必要な行にマウスカーソルを置き、
デバッグメニューの「トグルブレークポイント」コマンドを実行するか、
F9キーを押します。

ブレークポイントは同じ方法で無効に出来ます。

---------------
デバッギング開始

デバッギング処理を開始するため、プログラムファイルを開く必要があります。
ナビゲータウインドウで選択します。
次にデバックメニュー、あるいはスタートデバッギングコマンドを実行するか、
スタンダードツールバー、あるいはF5キーを押して実行します。
その後、デバックするプログラムは、
トレーデイングターミナルの別チャートにアタッチされます。
プログラムは、最初のブレークポイントに到達すると停止します。
実行の停止ポイントには、(右向きの)矢印マークが出ます。
そしてデバッギングタブがツールボックスに現れます。
左側には関数コールのスタックを表示します。
アプリケーションのデバッギングは、サーバから受信したデータを使い、
リアルコンデションで行われます。
デバッギングの為に生成されるテンポラリーチャートは
クライアント端末の常備チャートと同じものです。

Waching Expressions
デバッギング処理では、プログラム実行ステージの、
式(変数)の変化する値を観察できます。
それにはツールボックスウインドウのデバッギングタブの右側が使われます。

式を書き加えるのは次の方法で行います。
デバッギング中に、必要な式でコンテキストメニューを呼び出し、
アドウオッチコマンドを選択するか、Shift+F9キーを押します。
新しい行が表示されるので、
その後、式のフィールドで観察するパラメータの名前を入力します。
観察する式の名前を変えるには、
名前でマウス左ボタンをダブルクリックするか、
コンテキストメニューでEditコマンドを実行するか、
あるいはF2を押す必要があります。 
式を観察するウインドウで、簡単な数式の計算(加算、減算、乗算、割算)、
配列の値を見ることが出来ます。
例えば、配列のA[3][4]を入力します。
3と4はAの各次元でのポジションを現します。
これで、配列A[3][4]の値が表示されます。
観察する式にオブジェクトを加えると、
そのメンバーのリストの終わりにポインタを加えられ、
Ctrl+Spaceを押すことで表示されます。

Viewing Stack of Calls
ツールボックスウインドウのデバックタブ左側は、
スタックを観察するためのものです。
ここで、下記のコンポーネントを観察できます。

1、ファイルの名前(ここから関数が呼ばれる)
2、関数の名前
3、ファイルの行番号(ここで関数が呼ばれる)

-----------------------------
ステップバイステップ デバッギング

ステップバイステップデバッギングは
デバッグメニューかスタンダードツールバーコマンドが使われます。

Step Into
プログラムの実行を1ステップ行い、呼ばれた関数に入ります。
同じことがF11キーを押すことでも可能です。

Step Over
プログラムの実行を1ステップ行うが、関数には入りません。
同じことがF10キーを押すことでも可能です。

Step Out
プログラムの実行を、一つ前のステップ、あるいは一つ前のブレークポイントに戻します。
同じことはShift+F11キーを押しても可能です。

上記コマンドの実行は、デバッギング処理のためにストップしてから行います。
デバッギングのストップは、プログラムの実行がブレークポイントに到達すると自動的に行われます。
手動では、
「デバッグ」メニュー、あるいは「スタンダード」ツールバーの、
ポーズ(直訳ではブレークデバッギング)を使うか、
あるいはデバックの一時停止(直訳ではブレーク)キーを押すことで、
デバッギング処理を行うことが出来ます。
全てのブレークポイントは順番に行われます。

Breakinng,Continuing,Stopping,Debugging
ブレーキングポイントに到達すると、
プログラムデバッギング処理のための一時停止(直訳ではブレーク)が自動的に行わます。
しかし、デバッギング処理は手動で管理します。


Breaking
デバッギングでプログラムを実行し、
「デバッグ」メニュー、あるいは「スタンダード」ツールバーで、
ポーズ(直訳ではブレークデバッギング)コマンドを押すか、
一時停止(直訳ではブレーク)キーを押すと、
デバッギングは手動で止めることが出来ます。
その後、ステップバイステップでデバッギングを実行します。


continuing
自動あるいは手動で止った後、
デバッギングモードでプログラムの実行をさらに続けるためには、
「デバッギング」メニュー、あるいは「スタンダード」ツールバーで、
デバッグのスタートと解除(直訳ではコンテニューデバッギング)コマンドを実行するか、
F5キーを押します。

Stopping
デバッギングをストップするために、
「デバッギング」メニュー、「スタンダード」ツールバーで、
「デバッグを停止する」(直訳ではストップデバッギング)コマンドを実行するか、
Shift+F5キーを押す必要があります。
プログラムがストップした後、
デバッギングのために生成されたチャートが削除されクローズします。

デバッギングはMQL4,MQL5,MQHファイル以外は出来ません。
デバッギングの結果で出来るEX4/EX5ファイルは、配布が推奨されていません。


<訳注>
筆者のMQL4-MetaEditorは、version 5.00, build 1154ですが、
History Dataでのデバッギングは出来ません。
「デバッギング」メニューの(Start On History Data)コマンドは、
青色の表示にならず灰色のままです。
(Start On Real Data)コマンドは緑色になっており、
リアルタイムのデータでデバッギング出来ます。
また、MQL5のMetaEditor(2台あります)は、DebugコマンドだけのMetaEditorであったり、
あるいは
(Start On History Data)コマンドと(Start On Real Data)コマンドがあり、
どちらもカラーで、それぞれ青色、緑色の表示です。
現在のHistory Dataでのデバッギングは、MetaEditorで様々の状態です。
以下は、MetaEditorユーザーガイドにある説明を訳したものです。
将来ヒストリデータが使えるようになったら、役立ててください。

Debugging on History Data
トレーデイングロボットとテクニカルインデイケータは、
リアルタイムのデータでデバッギング出来るほか、
ヒストリーデータでもデバッグ出来ます。
プログラムは、必要なヒストリー期間でテスト出来ます。
デバッギングはビジュアルテストモードで、
ストラテジーテスターを動かします。
デバッギングチャートは、
テイックシーケンスのエミュレータをベースにします。
ヒストリーデータでデバッギングをするには、
ストラテジーテスターのMetaEditor settingsで、
テストするプログラムのパラメータの設定を行います。
プログラムコードでブレークポイントをセットし、
ヒストリーデータのデバッギングテストをスタートします。
ビジュアルテストでデバッギング処理を起動します。

------------------------------
MQL5プログラムのデバッギング 1

原文の場所は、
https://www.mql5.com/en/articles/654
です。


序文

この記事は、すでに言語を学んだが、まだプログラム開発を完全に
マスターしていないプログラマーに対して企画されたものです。
全てのプログラム開発者がデバッギングのときに遭遇する、
核心の問題に光を当てています。

デバッギングとは何か?
デバッギングの一つの段階は、
プログラムに生じるエラーを見つけ削除することです。
デバッギング処理中、開発者は可能な問題点を発見するため、
アプリケーションの解析を行います。
解析データは、変数とプログラムの動作を観察することで行います。
(何の関数が、いつ呼ばれたかなど。)

2つの相補的なデバッギング技術:

1、デバッガの使用
開発プログラムのステップバイステップの実行を観察。

2、スクリーン、ジャーナル、あるいはファイルにおける、
変数の「状態と関数」実施の相互的な表示。

読者はMQL5(アップグレードMQL4)の変数、構造体、
その他をすでに知っているとします。
しかし、まだ自分ではプログラムの開発はしていないとき、
まず最初に行うのはコンパイルです。
事実、これはデバッギングの最初のステージです。

1、コンパイレーション
コンパイレーションは、ハイレベルプログラミング言語から、
ローレベルにソースコードを変換します。
メタエデイターのコンパイラは、
ネイテイブバイトコードにプログラムを変換します。
これは暗号化プログラムの開発です。
バイトコードは32ビットと64ビットのオペレーティングシステムの両方で実施可能です。

デバッギングの最初のステージのコンパイレーションの話に戻します。
F7キー(あるいはコンパイルボタン)をクリックすると、
全てのエラーをリポートします。
「ツールボックス」ウインドウの「エラー」タブは、
発見されたエラーと場所を表示します。
ハイライトのカーソルにより、
エラーのラインを表示し、
Enterを押すと、エラーのある場所へ行きます。

コンパイルによるエラーは、2つのタイプのエラーのみです。

1、シンタックスエラー(赤色で表示)
ソースコードからそれらのエラーが除かれるまでコンパイルされない。

2、ワーニング(黄色で表示)
コードはコンパイルされます。しかし、ミスを修正する方が良い。

シンタックスエラーはしばしば不注意で生じます。
例えば、
「,」、「;」は変数を宣言するとき、簡単に混乱します。

int a; b; //不正
コンパイラはこの宣言ではエラーを返します。
正しい宣言は
int a, b; //正
あるいは、
int a; int b; //正
となります。

ワーニングは、プログラムを良くするためには無視すべきではありません。
(多くの開発者はそれらにあまり注意しません。)
MQL5(アップグレードMQL4)では、
コンパイルのワーニングは、
プログラムが生成されるが、計画どおりに動くか保障されません。

ワーニングは、隠れたメージャーな影響の、単なる氷山の一角です。

2つの変数を比較します。
if(a==b){ } //もしaがbと同じとき、そのときは~
しかし、省略したり、忘れた為に、
「==」の代わりに、「=」を使用するとします。
この時、コンパイラはコードを次のように解釈します。
if(a=b){ }
//bをaへ指定、もしaがtrueなら、そのときは...
(MQL4と違い、MQL5では使用できます。)

省略はプログラムをドラマチックを変えます。
そのため、コンパイラはこのラインでワーニングを出します。

Lets sum it up
コンパイレーションはデバッギングの最初のステージです。
コンパイラワーニングは無視すべきではありません。

------------------------------
MQL5プログラムのデバッギング 2

デバッガ
セカンドステージではデバッガ(F5ホットキー)が使用されます。
デバッガは、ステップバイステップでプログラムのエミュレーションモードでの実行を開始します。
デバッガはメタエデイタ5(アップグレードメタエデイタ4)の新しい機能です。
これは古いメタエデイタ4にはありませんでした。
プログラマーに経験がないのは、古いメタエデイタ4にデバッガが無かった為です。

デバッガインターフェイスは3つのメインボタンと3つの補助ボタンを持ちます。
1、スタート(F5)---デバッギングの開始
2、ポーズ(Break)---デバッギングの一時中断
3、ストップ(Shift+F5)---デバッギングの中止
4、ステップイントゥー(F11)---このラインで呼ばれた関数の内部へ移動
5、ステップオーバー(F10)---デバッガはこのストリングで呼ばれた関数を無視し、次のラインへ移動
6、ステップアウト(Shift+F11)---現在の位置の関数内部から外へ移動

これがデバッガのインタフェイスです。
しかし、どのようにそれを使いますか。

プログラムデバッギングは、
プログラマーがDebugBreak()という特殊な関数をセットしたラインからスタートします。
あるいはツールバーのブレックポイントのオンオフか、
F9ボタンをクリックしセットした、
ブレークポイントからスタートします。
ブレークポイントが無いときは、
デバッガはプログラムを実行し簡単にデバッギングの成功をリポートします。
しかし、何も見ることは出来ません。
DebugBreakを使い、興味の無いコードをスキップし、
トラブルの考えられるラインから、
プログラムのチェックをステップバイステップで開始できます。
すなわち、デバッガをスタートし、
DebugBreakを正しい場所に置き、
プログラムを実行します。

次はプログラムに起きている事をどのように理解するかです。
まず始めにデバッガウインドウの左側を見ます。
ロケーション位置の関数名とライン番号を見ます。
次にウインドウの右側を見ます。
空ラインのエクスプレッションフィールドに任意の変数の名前を入力します。
変数の名前を入力し、現在の値フィールドの値を見ます。
変数はShift+F9ホットキーを使うか、
下に示されたコンテキストメニューから、
AddWatchを使い選択し加えることができます。

このようにラインで重要な変数の値を見ることで、
コードラインのトラッキングが出来ます。
全てを解析しプログラムが正しい操作をしているかどうか理解できます。

ローカルで宣言された変数は、宣言の外では心配する必要はありません。

Unknown identifierの値が表示されたときは、
変数が宣言されていないことを意味しています。
それはデバッガのエラーではありません。
変数の範囲に入ると値とタイプを表示します。
これらがメインデバッガの特徴です。

テスターセクションはデバッガが出来ない事を行います。

------------------------------
MQL5プログラムのデバッギング 3

プロファイラ

コードプロファイラはデバッガの重要な追加機能です。
事実これは、最適化を含むプログラムデバッギングにおける最終ステージです。
プロファイラは、
メタエデイタ5(アップグレードメタエデイタ4)のメニューから、
「スタートプロファイリング」ボタンをクリックし起動します。
デバッガで提供されている、
ステップバイステップによるプログラム解析の代わりに、
プロファイラを実行します。
プログラムがインデイケータやEAのときは、
プロファイラはプログラムがアンロードされるまで動いています。
アンロードはチャートからインデイケータやEAを除去することで行います。
あるいは、「ストッププロファイリング」をクリックすることで、
アンロード出来ます。
プロファイリングは重要な統計情報を提供してくれます。
何回各関数が呼ばれたか、
その関数の実行がどれくらいの時間行われたか、
それらの統計データを提供します。
パーセントの項目の統計に、たぶん少し驚かされるでしょう。
統計データは、ネスト関数で構成されていないことを理解する必要があります。
したがって、パーセンテージの値の合計は大きく100%を超えます。
しかし、それにも関わらず、プロファイラは依然パワフルなツールです。
どの関数のスピードを最適化し、
メモリーをセーブ出来るのはどこかを、
ユーザに教えるためのプログラム最適化ツールとして依然留まっています。

4.Interactivity(対話性)
メッセージ表示関数Print、Commentはどちらも主要なデバッギングツールです。
始めに、それらは非常に簡単に使用できます。
二番目に、
以前のバージョンから今のバージョンへ移行したプログラマは、
すでにそれを知っています。
「Print」関数は、Expertツールタブに、
ログファイル、テキスト文字としてパラメータを表示します。
送信時間と関数コールのプログラムの名前がテキストの左に表示されます。

デバッギングでは、関数はどのような値がその変数に含まれているかを定義するため使われます。
変数に加えて、それら関数の呼び出しシーケンスを知る必要が時々あります。
そんな時、「__FUNCTION__」と「__FUNSIG__」マクロが使用されます。
最初のマクロは、呼ばれた関数の名前をストリングタイプで返します。
二番目のマクロは、呼ばれた関数のパラメータのリストが加えられます。

下の例はマクロの使用例です。

void myfunc(int a)
{
Print(__FUNCSIG__);
}

オーバーロード関数(同じ名前だがパラメータが違う)の違いを知るために、
「__FUNSIG__」マクロの方が好まれます。


何回も呼び出しのスキップが要求されているか、あるいはさらに
特殊な関数コールでフォーカスを要求されることがあります。
この目的のため、Print関数をifコンデションでプロテクトさせることが出来ます。
例えば、
1013回繰り返した後にPrint関数が呼ばれることがあります。

下記はその例です。

void myfunc(int a)
{

static int cnt=0;

if(cnt==1013)
Print(__FUNCSIG__," a=",a);

cnt++;
}

------------------------------
MQL5プログラムのデバッギング 4

前回の続き

同じことはComment関数で行うことが出来ます。
Comment関数はチャートの左上にコメントを表示します。
これは非常に便利です。どこでデバッグしていても切り替えなくて大丈夫です。
しかし、この関数を使うとき、新しいコメントは前のコメントを消去していまいます。
便利であるにもかかわらずこれは不便です。
この欠点を改善するため、
変数に新しいストリングを書き加えるメソッドを適用します。
始めにstringタイプの変数が宣言され(最も多いのはグローバルタイプ)、
そして空白で初期化します。
新しいテキストストリングは
始めにラインフィードキャラクタを置き、
終わりは以前の変数の値を置きます。

stringcom="";

void myfunction(int a)
{
static int cnt =0;

com = (__FUNCSIG__+" cnt = "+(string)cnt+"\n")+com;

Comment(com);

cnt++;

}


詳細にプログラムのコンテンツを見るための他の方法を以下に記載します。
Print関数とComment関数は大きなデータ変数、高速プリントに適しているわけではありません。
呼び出しは混乱の原因になり、そして遅いので、
Print関数は変化を表示するのに十分ではありません。
Comment関数では、詳細な関係、調査が出来ません。

ファイルにプリントするのは、
呼び出しシーケンス、あるいは長く大きなデータのチェックが必要なときです。
データ出力メソッドは便利な方法です。
しかし、プリントは各々のくり返しでは使用すべきでなく、
ファイルの終わりに使用すべきです。

一方ストリングの値として保存されるデータは、
上記の基本的記述方式ではなく、
各々のくり返しに使用されます。
(唯一の違いは、新しいデータが終わりに追加される事です。)

以下のtest.mql4のコードはテスト用に筆者が手直ししたものです。
コンパイルの後、チャートにアタッチします。
時間が長いとデータが大きくなるので、1分くらいで終了します。
test.mql4をチャートから削除します。
Debugging1.txtファイルが、
メタエディター左側ナビゲータのFILEフォルダーに作成されます。
メタエディターでファイルを開くと内容は以下の様になっています。

void myfunc(int) cnt=0
void myfunc(int) cnt=1
void myfunc(int) cnt=2
void myfunc(int) cnt=3

void myfunc(int) cnt=40
void myfunc(int) cnt=41

+------------------------------------------------------------------+
test.mql4

#property copyright "Copyright 2015, T.S."
#property link "http://"
#property version "1.00"
#property strict
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+

int OnInit()
{

return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
string com="";

void OnDeinit(const int reason)
{
WriteFile();
Comment("");
}
//+------------------------------------------------------------------+

void myfunc(int a)
{
static int cnt=0;

com+=__FUNCSIG__+" cnt="+(string)cnt+"\n";

cnt++;

//--- here is some code of the function itself
//チェック用
//Comment(a);
}
//+------------------------------------------------------------------+
void WriteFile(string name="Debugging1")
{
//--- open the file
ResetLastError();
int han=FileOpen(name+".txt",FILE_WRITE|FILE_TXT|FILE_ANSI," ");
//--- check if the file has been opened
//チェック用
//han=-1;
if(han!=INVALID_HANDLE)
{
//チェック用
// Print(com);
FileWrite(han,com);
FileClose(han);
}
else
Print("File open failed "+name+".txt, error",GetLastError());
}
//+------------------------------------------------------------------+
void OnTick()
{
//---
myfunc(100);
}
//+------------------------------------------------------------------+
コード内には、
コメント(//チェック用)の下に、
//Comment(a);//han=-1;// Print(com);のコメントがあります。
コンパイルがうまくいかないときは、
//をはずして試して見ると良いでしょう。
//+------------------------------------------------------------------+

WriteFile()関数はOnDeinitで呼ばれます。
プログラムに生じた変化はすべてファイルに記載されます。

Note:
もしログ(記録)が非常に大きいときは、
複数に分けて記録するのが賢い方法です。
ベストな方法はストリングタイプの配列のセルと、
テキスト変数のコンテンツを用意することです。
各々100万~200万のstrings(エントリーが頻発しない)にしなければなりません。
最初に注意することは、
変数のオーバーフローによるデータロスを避ける必要があります。
(ストリングタイプのハードな開発では、私の方法はがっかりさせない。)
二番目にはもっと大事なことですが、
エディターで大きなファイルを表示しないで、
幾つかのファイルに分けてデータを表示することです。

保存するストリングの量をコンスタントに追跡せずに、
ファイルの作業を3つに分けることも出来ます。
最初の部分はファイルを開くこと、
2番目は各々順にファイルを書くこと、
3番目はファイルをクローズすることです。

//--- open the file
int han=FileOpen("Debugging.txt",FILE_WRITE|FILE_TXT|FILE_ANSI," ");
//--- print data
if(han!=INVALID_HANDLE) FileWrite(han,com);
if(han!=INVALID_HANDLE) FileWrite(han,com);
if(han!=INVALID_HANDLE) FileWrite(han,com);
if(han!=INVALID_HANDLE) FileWrite(han,com);
//--- close the file
if(han!=INVALID_HANDLE) FileClose(han);

しかし、この方法は警告しておかなければなりません。
もしこのプログラムの実行に失敗すると(例えばゼロ除算で)、
オペレーテイングシステムでは管理出来ないオープンファイルとして受け取られるでしょう。
私は推奨しませんが、
各々の順次くり返しで、フルにopen_write_closeループを使うことも出来ます。
しかし私の個人的な経験ではハードドライブは、2~3ヶ月しかもたないでしょう。

------------------------------
MQL5プログラムのデバッギング 5

テスター

エキスパートアドバイザーのデバッギングのとき、
特別にifコンデションを生かす必要が生じる事があります。
しかし、上記では、
リアルタイムでのみ出来ますので、
結局このifコンデションは生かされたまま、長時間待たされるかもしれません。
実際、この特別なトレードコンデションはめったに生じないかもしれません。
あるいは、発生するかもしれませんが、
何ヵ月も待たされる事になるかも知れません。

我々に何が出来るでしょうか。
そんなときストラテジーテスターが助けてくれます。
デバッギングではPrint関数とComment関数を使用します。
最初、Comment関数は状況を評価するために通常使われます。
Print関数はさらに詳細な解析をするため使われます。

ストラテジーテスターでは、
テスターログに表示データを保管します。
正しい期間でエキスパートアドバイザーを開始するには、
期間をローカライズ(日付けと時間を使用:ここで間違いが発生しやすい)します。
そして、ストラテジーテスターに必要なデータをセットし、
設定は全テック、ビィジュアルモードで開始します。

メタエデイター4以降、このデバッギングメソッドを使うことが好まれます。
これが実行プログラムのデバッグのほとんど唯一の方法です。

上記テスターログのデータは、筆者の実施結果では以下のフォルダに出来ます。

1.(MT4-->ファイル-->データフォルダを開く-->tester-->logs-->日付.txt:)
始にプログラムを実施してもデータファイルは出来ない。
先にエキスパートアドバイザープログラムを最適化する。
そのとき上記フォルダにテキストファイルが出来る。
その後、プログラムを実施した後のテスターログ結果がこのファイルに追加される。


2.(MT4-->ファイル-->データフォルダを開く-->tester-->プログラムの名前.ini)
プログラムのテスト時の構成設定ファイルが上記フォルダに出来る。


------------------------------
MQL5プログラムのデバッギング 6

OOPでのデバッギング

オブジェクトオリエントプログラミングは、
デバッギング処理を頻繁に行います。
デバッギングの処理の時、
関数のみの名前で簡単にプログラムをナビゲート出来ます。
しかし、OOPでは時々そこから呼ばれる異なるメソッドのオブジェクトを知る必要があります。
オブジェクトが継承を使い仮想的に設計されているときは特に重要です。

この場合はテンプレートが助けてくれます。
テンプレート関数はストリング戻し値として、ポインタタイプの値を受け取ります。
(テンプレートとはコンパイラのサポートするマクロ、型推論機構です。
詳細はメーリングリストホームページの共有ファイルにあります。:
18.Function templates.txt (7KB))

template
string GetTypeName(const T &t){
return(typename(T));
}


次のデバッギングでは、私はこのプロパティを使用します。

//ベースクラスはストリングタイプの変数を持つ。
class CFirst
{
public:
string m_typename;

CFirst(void) { m_typename=GetTypeName(this); }
~CFirst(void) { }
};


//派生クラスはベースクラスの変数の値を変える。
class CSecond : public CFirst
{
public:

CSecond(void) { m_typename=GetTypeName(this); }
~CSecond(void) { }
};

べースクラスはストリングタイプの変数を持ち、
派生クラスはストリングタイプの変数の値を使用します。
すなわち、マクロが呼ばれたとき、関数の名前ばかりでなく、
この関数が呼ばれるオブジェクトタイプを受け取り、
m_typename変数として加えます。

ポインタ自身はオブジェクトの正しい認識のため派生されます。
ポインタは番号でオブジェクトを識別されます。

オブジェクト内部では、これは次のように行われます。

Print((string)this);

オブジェクト名のストリング変数は各クラスの内部で使用することができます。
その場合、オブジェクト生成時のコンストラクタのパラメータとして、
オブジェクトの名前を渡すことが出来ます。
これは番号でオブジェクトを区別するばかりでなく、
各プロジェクトが何を意味しているかを(名前をつけるとき)理解出来るようにします。
一方オブジェクトの外では次のようになります。

Print((string)GetPointer(pointer));


以下のコードは筆者の使用例です。
チャートの動作時(日曜日、チャートは日曜は動いていません)に使用すると、
チャート左上にCFirstを表示します。

//+---------------------------------------+
#property copyright "Copyright 2015, T.S."
#property link "http://"
#property version "1.00"
#property strict

template
string GetTypeName(const T &t){
return(typename(T));
}
//+---------------------------------------+
class CFirst
{
public:
string m_typename;

CFirst(void) { m_typename=GetTypeName(this); }
~CFirst(void) { }
};

class CSecond : public CFirst
{
public:

CSecond(void) { m_typename=GetTypeName(this); }
~CSecond(void) { }
};

//+---------------------------------------+
int OnInit()
{
return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
//---
Comment("");
}

void OnTick()
{
//---
//クラス
CFirst f;
//CSecond f;

string s = f.m_typename;

Comment(s);

}
//+---------------------------------------+
プログラムコード内の
//クラス
CFirst f;
//CSecond f;

これを
//CFirst f;
CSecond f;

に変更すると、
チャート左上に、
CSecondを表示します。
------------------------------

以下はオブジェクトの外での使用方法例です。
参考にしてください。。

class CItem
{
...
}

void OnStart()
{

CItem items[10];

item=GetPointer(items[i]);
if(CheckPointer(item)!=POINTER_INVALID){...;}
...

}

//+---------------------------------------+
GetPointerの説明
(MQL5リファレンスより参照)

The function returns the object pointer.

void* GetPointer(
any_class  anyobject
);

[in] Object of any class.

[Return Value]

The function returns the object pointer. 


-----------------------------------------------------END