GetLastError()の間違った使い方…。
先日リクエストを頂いた、GetLastError()の件ですが、忘れないうちに説明しておきたいと思います。
まずは、とあるEAにあったGetLastError()の間違った使い方のサンプルから。
#include// ←エラーコードをメッセージとして表示するErrorDescription を使う時必要になる。 // void subCheckError(int ticket, string Type) { if(ticket>0) { if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print(Type + " order opened : ",OrderOpenPrice()); } else Print("Error opening " + Type + " order : (",GetLastError(),") ", ErrorDescription(GetLastError())); }
OrderSend後に、ticket が取れていなかったら、subCheckError関数でエラーメッセージを表示しようとしているのですが、この中にバグを見つけられますか?
以前の記事を読まれている人ならすぐ分かると思うのですが、
else Print("Error opening " + Type + " order : (",GetLastError(),") ", ErrorDescription(GetLastError()));
この行で、GetLastError() を2度呼び出しているのが間違いです。
GetLastError()は、オンラインヘルプに書かれている通り、1度呼び出すと、エラーコードを格納しているlast_error変数をゼロにリセットします。
そのため、2度目の呼び出しでは、ゼロが返ってくることになり、本来エラーが発生しているにもかかわらず、"no error" というメッセージが表示されてしまうのです。
正しく書き直すとしたら、
#include// // void subCheckError(int ticket, string Type) { err=GetLastError();←1度だけの呼び出しにした if(ticket>0) { if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print(Type + " order opened : ",OrderOpenPrice()); } else Print("Error opening " + Type + " order : (",err,") ", ErrorDescription(err)); }
とすれば、2度呼び出しのバグは解決できそうです。オンラインヘルプの参考コードも同様の書き方になっていると思います。
実際は、このEA の場合、別の関数内で
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,aStopLoss,aTakeProfit,TicketComment,MagicNumber,0,Green); err=GetLastError();
と書かれていて、OrderSend 直後に既に GetLastError が呼ばれているので、subCheckError の中身をいくら書き換えても解決しませんでした....orz
GetLastError() のような一度しか呼べない関数は、エラーの起きる可能性のある命令の直後に呼んで err のような変数に保持しておくのが良いと思います。遠く離れた場所で呼び出そうとすると、うっかりミスをすることが多いです。