バグの原因を探すとき、怪しい処理を一時的にコメントアウトして、
動きが変わるかどうかを確認する方法は定番のデバッグ手法です。
しかし、/* */で囲んだつもりが意図しない場所で終わっていたり、
確認が終わったあとに直し忘れたまま提出してしまったりする事故も、
実はよく起きています。
この記事では、コメントアウトでコードを一時的に無効化する正しいやり方と、
よくある事故の避け方について解説します。
・//と/* */、どちらでコメントアウトすべきか
・/* */が入れ子にできない仕様が引き起こす事故
・直し忘れを防ぐ工夫
・#ifdefを使った、より安全な無効化の方法
なぜコメントアウトで切り分けるのか
まず、デバッグ手法としてのコメントアウトの位置づけを確認します。
怪しい処理を切り離して動作を確認する
EAやインジケーターが思った通りに動かないとき、
怪しいと感じた処理を一時的に無効化し、
問題が再現するかどうかを確認するという切り分け方法があります。
既刊のインデント・コメント記事との違い
既刊のインデントとコメントの基本記事は、
//と/* */の基本的な書き方を紹介する内容でした。
本記事は、その構文を前提に、
バグ調査のための一時無効化という実務的な使い方に絞って解説します。
この記事で扱う範囲
コメントアウトでの無効化方法、よくある事故、
より安全な代替手段である条件付きコンパイルまでを扱います。
//と/* */、どちらを使うべきか
2種類のコメント記法を、無効化の目的に応じて使い分けます。
1行だけ無効化するなら//
// Print("デバッグ用: ", lot); // この行だけ無効化
1行だけを確認したい場合は、行頭に//を付けるのが最も簡単です。
複数行まとめて無効化するなら/* */
/*
OrderSend(Symbol(), OP_BUY, lot, Ask, 3, 0, 0);
Print("発注しました");
*/
数行から数十行をまとめて無効化したい場合は、/* */で囲みます。
公式リファレンスでの定義
MQL4公式リファレンスでは、//は改行までの単一行コメント、
/* */は開始から終了までの複数行コメントと定義されています。
/* */が入れ子にできない仕様が引き起こす事故
複数行コメントのよくある事故を確認します。
実際に起きる事故の例
/* double price = Ask; /* 現在の買値 */ OrderSend(Symbol(), OP_BUY, lot, price, 3, 0, 0); */
この例では、内側の/* 現在の買値 */で最初の/*が閉じてしまい、
意図したOrderSendの行まで無効化されません。
なぜ閉じてしまうのか
・MQL4/MQL5の複数行コメントは入れ子にできない仕様
・最初に見つかった*/で即座にコメントが終了する
・外側で囲んだつもりの範囲が、意図せず有効なコードに戻る
避け方
すでに/* */のコメントが含まれている範囲を、
さらに/* */で囲みたい場合は、
内側のコメントを一時的に//へ書き換えるか、
4章で解説する条件付きコンパイルを使う方法があります。
#ifdefを使った、より安全な無効化
コメントアウトより事故が起きにくい代替方法を紹介します。
条件付きコンパイルの書式
#define DISABLE_ORDER_SEND #ifndef DISABLE_ORDER_SEND OrderSend(Symbol(), OP_BUY, lot, Ask, 3, 0, 0); #endif
#defineで識別子を定義し、#ifndefで「定義されていない場合だけ」、
という条件分岐でコードブロックを無効化できます。
コメントアウトより安全な理由
#ifdef/#ifndefはコメントの入れ子に関する制約を受けないため、
ブロックの中に別のコメントが含まれていても、
意図しない場所で無効化が解除される事故が起きません。
使い分けの目安
1〜2行の単純な無効化なら//で十分ですが、
内部に/* */コメントを含む複雑なブロックを無効化する場合は、
#ifdef/#ifndefを使うほうが安全です。
直し忘れを防ぐ工夫
デバッグ後の後始末でよくある事故を防ぎます。
デバッグ用コメントアウトを残したまま提出する事故
一時的に無効化したつもりが、修正範囲を忘れてそのままコンパイル・提出し、
本来必要な処理が実行されないまま運用されるという事故が起こり得ます。
目立つ合図を付けておく
// TODO: デバッグ用に無効化中。確認後に戻す /* OrderSend(Symbol(), OP_BUY, lot, Ask, 3, 0, 0); */
TODO等の検索しやすい合図をコメント内に残しておくと、
あとで検索して見つけやすくなります。
MetaEditorの検索機能で確認する
提出前にMetaEditorの検索機能で「TODO」や「/*」を検索し、
無効化したまま忘れている箇所が残っていないか確認する習慣をつけてください。
よくある注意点
実務でつまずきやすい点をまとめます。
文字列の中の記号は無効化されない
・Print(“//これはコメントではない”)のように文字列内の//は影響を受けない
・コメントは構文として解釈される部分にのみ有効
・文字列中の記号とコードのコメントを混同しない
関数定義の途中を無効化すると構文エラーになる
関数の中身だけを無効化するつもりで中括弧の外まで囲んでしまうと、
対応する中括弧の数が合わなくなり、コンパイルエラーになります。
EAとインジケーターで挙動の違いはない
コメント・条件付きコンパイルの仕様自体は、
EA・インジケーター・スクリプトのどれであっても同じです。
MQL4とMQL5の違い
コメント・条件付きコンパイルに関する2言語の違いを確認します。
コメントの構文自体は共通
//・/* */の書き方、入れ子にできない仕様は、
MQL4とMQL5で共通です。
#ifdef系も共通
条件付きコンパイルの書式、__MQL4__・__MQL5__といった標準マクロも、
MQL4/MQL5の両方で使えます。
__MQL4__/__MQL5__マクロの活用例
同じソースコードをMQL4/MQL5両対応にしたい場合、
#ifdef __MQL5__で言語ごとに異なる処理を切り替える使い方もできます。
よくある質問
コメントアウトについて、よくある疑問に回答します。
・1〜2行の無効化は//、複数行は/* */が基本
・/* */の中に/* */を入れない
・提出前にTODOや/*の検索で直し忘れを確認する
コメントアウトしたコードはコンパイル後に残りますか?
いいえ。コメントはコンパイル時に無視されるため、
実行ファイルには影響しません。
デバッグが終わったコメントアウトはすぐ消すべきですか?
一時的な確認作業であれば、確認後は元に戻すか削除するのが基本です。
残す場合は、TODO等の合図と理由を書いておくことをおすすめします。
#ifdefを使うと実行速度に影響しますか?
いいえ。条件付きコンパイルはコンパイル時に判定されるため、
実行時の速度には影響しません。
【MQL】コメントアウトでコードを一時的に無効化する正しいやり方について解説してみた(/* */の入れ子事故と#ifdefでの安全な代替):まとめ
コメントアウトは、バグの原因を切り分けるための手軽な手段ですが、
/* */が入れ子にできない仕様による事故や、直し忘れのリスクがあります。
1〜2行は//、複数行は/* */を基本にしつつ、
複雑なブロックを無効化する場合は#ifdef/#ifndefを使うほうが安全です。
提出前にTODOや/*を検索して、直し忘れがないかを確認する習慣をつけてください。
コメント