乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      MQL4程序的常見錯誤以及如何避免它們

       寒木蕭條 2016-08-17

      介紹

      一些較舊的程序可能在新版本的MQL4編譯器中返回錯誤。

      為了避免關(guān)鍵的程序完成,以前版本的編譯器在運(yùn)行環(huán)境中處理了許多錯誤。例如,除數(shù)為零或數(shù)組越界都是嚴(yán)重錯誤,并通常會導(dǎo)致應(yīng)用程序崩潰。這些錯誤只在一些狀態(tài)下針對某些變量值而發(fā)生。閱讀這篇文章了解如何處理這樣的情況。 

      新的編譯器可以檢測實(shí)際或潛在的錯誤源并提高代碼質(zhì)量。

      在這篇文章中,我們討論了舊程序編譯過程中檢測到的可能出現(xiàn)的錯誤,以及解決這些問題的方法。

      1. 編譯錯誤
      2. 運(yùn)行時間錯誤
      3. 編譯器警告

      1編譯錯誤

      如果程序代碼中包含錯誤,則它不能被編譯。

      要完全控制所有的錯誤,建議使用嚴(yán)謹(jǐn)?shù)木幾g模式,它通過以下指令來設(shè)置:

      #property strict

      這種模式大大簡化了故障排除。 


      1.1. 與關(guān)鍵字一致的標(biāo)識

      如果變量或函數(shù)的名稱與其中一個關(guān)鍵字一致

      int char[];  // incorrect
      int char1[]; // correct
      int char()   // incorrect
      {
       return(0);
      }

      編譯器會返回一個錯誤信息:

      圖1. 錯誤“unexpected token(非預(yù)期標(biāo)記)”和“name expected(預(yù)期名稱)”

      圖1. 錯誤“unexpected token(非預(yù)期標(biāo)記)”和“name expected(預(yù)期名稱)”

      要解決這個錯誤,您需要使用變量或函數(shù)的正確名稱。


      1.2. 變量和函數(shù)名的特殊字符

      如果變量或函數(shù)名稱中包含特殊字符($,@,點(diǎn)): 

      int $var1; // incorrect
      int @var2; // incorrect 
      int var.3; // incorrect
      void f@()  // incorrect
      {
       return;
      }

      編譯器會返回一個錯誤信息:

      圖2. 錯誤“unknown symbol(未知交易品種)”與“semicolon expected(預(yù)期分號)”

      圖2. 錯誤“unknown symbol(未知交易品種)”與“semicolon expected(預(yù)期分號)”

      要解決這個錯誤,您需要使用正確的函數(shù)或變量名。


      1.3. 使用switch操作符的錯誤

      在舊版本的編譯器中,您可以在switch操作符的表達(dá)式和常量中使用任何值:

      void start()
        {
         double n=3.14;
         switch(n)
           {
            case 3.14: Print("Pi");break;
            case 2.7: Print("E");break;
           }
        }

      在新的編譯器中,switch操作符的常量和表達(dá)式必須是整數(shù),所以當(dāng)您嘗試使用這樣的結(jié)構(gòu)時會發(fā)生錯誤:

      圖3. 錯誤“illegal switch expression type(非法switch表達(dá)式類型)”和“constant expression is not integral(常量表??達(dá)式不是整數(shù))”

      圖3. 錯誤“illegal switch expression type(非法switch表達(dá)式類型)”和“constant expression is not integral(常量表??達(dá)式不是整數(shù))”

      在這種情況下,您可以使用明確的數(shù)值比較,例如:

      void start()
        {
         double n=3.14;
         if(n==3.14) Print("Pi");
         else
            if(n==2.7) Print("E");
        }

      1.4. 函數(shù)返回值

      除了空值外的所有函數(shù)都應(yīng)該返回聲明的類型值。例如:

      int function()
      {
      }

      在嚴(yán)謹(jǐn)?shù)木幾g模式下發(fā)生錯誤:


      圖4. 錯誤“not all control paths return a value(并非所有的控制路徑返回一個值)”

      圖4. 錯誤“not all control paths return a value(并非所有的控制路徑返回一個值)”

      在默認(rèn)的編譯模式下,編譯器會返回一個警告:

      圖5. 警告:“not all control paths return a value(并非所有的控制路徑返回一個值)”

      圖5. 警告:“not all control paths return a value(并非所有的控制路徑返回一個值)”

      如果函數(shù)的返回值與聲明的不匹配:

      int init()                         
        {
         return;                          
        }

      在嚴(yán)格的編譯中會檢測錯誤:

      圖6. 錯誤“function must return a value(函數(shù)必須返回一個值)”

      圖6. 錯誤“function must return a value(函數(shù)必須返回一個值)”

      在默認(rèn)的編譯模式下,編譯器會返回一個警告:

      圖7. 警告 'return - function must return a value(回報 - 函數(shù)必須返回一個值)”

      圖7. 警告 'return - function must return a value(回報 - 函數(shù)必須返回一個值)”

      要解決這樣的錯誤,添加帶有相應(yīng)類型返回值的return操作符到函數(shù)代碼。



      1.5. 函數(shù)參數(shù)數(shù)組

      在函數(shù)參數(shù),數(shù)組現(xiàn)在只引用傳遞。 

      double ArrayAverage(double a[])
      {
       return(0);
      }
      在嚴(yán)謹(jǐn)?shù)木幾g模式下,該代碼將導(dǎo)致錯誤:

      圖8. 編譯器錯誤“arrays passed by reference only(數(shù)組只引用傳遞)”

      圖8. 編譯器錯誤“arrays passed by reference only(數(shù)組只引用傳遞)”

      在默認(rèn)的編譯模式下,編譯器會返回一個警告:

      圖9. 編譯器警告“arrays passed by reference only(數(shù)組只引用傳遞)”

      圖9. 編譯器警告“arrays passed by reference only(數(shù)組只引用傳遞)”

      要修復(fù)此錯誤,您必須通過在數(shù)組名稱之前添加前綴來指定數(shù)組是通過引用傳遞的:

      double ArrayAverage(double &a[])
      {
       return(0);
      }

      但應(yīng)注意的是,現(xiàn)在常量數(shù)組 (Time[]Open[]High[]Low[]Close[]Volume[]) 不能引用傳遞。例如,下面的調(diào)用:

      ArrayAverage(Open);

      無論何種編譯模式都會導(dǎo)致錯誤:

      圖10. 錯誤'Open' - constant variable cannot be passed as reference(‘打開’ - 常量變量不能引用傳遞)

      圖10. 錯誤'Open' - constant variable cannot be passed as reference(‘打開’ - 常量變量不能引用傳遞)

      為了避免這些錯誤,從常量數(shù)組??復(fù)制所需的數(shù)據(jù):

         //--- an array that stores open price values
         double OpenPrices[];
         //--- copy the values of open prices to the OpenPrices[] array
         ArrayCopy(OpenPrices,Open,0,0,WHOLE_ARRAY);
         //--- function call
         ArrayAverage(OpenPrices);



      2. 運(yùn)行時間錯誤

      程序代碼執(zhí)行過程中出現(xiàn)的錯誤稱為運(yùn)行時間錯誤。這種錯誤通常是依賴于程序的狀態(tài),并與變量的不正確的值相關(guān)聯(lián)。 

      例如,如果變量用作數(shù)組元素的索引,其負(fù)值將不可避免地導(dǎo)致數(shù)組超出范圍的錯誤。


      2.1. 數(shù)組超出范圍

      訪問指標(biāo)緩沖區(qū)時常常在指標(biāo)中發(fā)生這個錯誤。該IndicatorCounted()函數(shù)返回自上次指標(biāo)調(diào)用的不變的柱數(shù)。先前計算的柱的指標(biāo)值不需要重新計算,所以為了更快的計算,您只需要處理最后的幾個柱。 

      大部分使用這種計算優(yōu)化的方法的指標(biāo)看起來如下:

      //+------------------------------------------------------------------+
      //| Custom indicator iteration function                              |
      //+------------------------------------------------------------------+
      int start()
        {
         //--- some calculations require no less than N bars (e.g. 100)      
         if (Bars<100) // if less bars are available on a chart (for example on MN timeframe)    
           return(-1); // stop calculation and exit
      
         //--- the number of bars that have not changed since the last indicator call
         int counted_bars=IndicatorCounted();
         //--- exit if an error has occurred
         if(counted_bars<0) return(-1);
            
         //--- position of the bar from which calculation in the loop starts
         int limit=Bars-counted_bars;
      
         //--- if counted_bars=0, reduce the starting position in the loop by 1,   
         if(counted_bars==0) 
           {
            limit--;  // to avoid the array out of range problem when counted_bars==0
            //--- we use a shift of 10 bars back in history, so add this shift during the first calculation
            limit-=10;
           }
         else //--- the indicator has been already calculated, counted_bars>0
           {     
            //--- for repeated calls increase limit by 1 to update the indicator values for the last bar
            limit++;
           } 
         //--- the main calculation loop
         for (int i=limit; i>0; i--)
         {
           Buff1[i]=0.5*(Open[i+5]+Close[i+10]) // values of bars 5 and 10 bars deeper to history are used
         }
      }

      通常counted_bars==0的情況處理不當(dāng)(初始限制持倉應(yīng)該通過等于相對循環(huán)變量的1 +最大指數(shù)的值來降低)。

      另外,請記住,在執(zhí)行start()函數(shù)的時候,我們可以從0到Bars ()-1的訪問指標(biāo)緩沖區(qū)的數(shù)組元素。如果您需要使用無指標(biāo)緩沖區(qū)的數(shù)組,那么按照指標(biāo)緩沖區(qū)的當(dāng)前大小使用ArrayResize()函數(shù)來增加其大小。也可以通過調(diào)用用作參數(shù)的指標(biāo)緩沖區(qū)的 ArraySize()來獲得元素地址的最大指數(shù)。


      2.2. 除數(shù)為零

      當(dāng)除法運(yùn)算中除數(shù)為零時則會發(fā)生零除的錯誤:

      void OnStart()
        {
      //---
         int a=0, b=0,c;
         c=a/b;
         Print("c=",c);
        }

      當(dāng)您運(yùn)行這個腳本時,專家選項卡會出現(xiàn)一條錯誤的消息,并且程序關(guān)閉:

      圖11. 錯誤消息“zero divide(除數(shù)為零)”

      圖11. 錯誤消息“zero divide(除數(shù)為零)”

      當(dāng)除數(shù)的值由任何外部數(shù)據(jù)值來決定時,通常會出現(xiàn)此錯誤。例如,如果交易參數(shù)進(jìn)行分析,如果沒有新建訂單,那么已用預(yù)付款的值等于0。另一個例子:如果要從一個文件讀取分析數(shù)據(jù),如果該文件不可用,那么我們也不能保證正確的操作。所以您應(yīng)該考慮到這樣的情況并正確地處理它們。

      最簡單的方法是除法運(yùn)算前檢查除數(shù)并報告不正確的參數(shù)值:

      void OnStart()
        {
      //---
         int a=0, b=0,c;
         if(b!=0) {c=a/b; Print(c);}
         else {Print("Error: b=0"); return; };
        }

      這不會導(dǎo)致嚴(yán)重的錯誤,但是不正確參數(shù)值的消息一出現(xiàn)則程序即關(guān)閉:

      圖12. 不正確的除數(shù)消息

      圖12. 不正確的除數(shù)消息


      2.3. 當(dāng)前字符用0替代NULL 

      在舊版本的編譯器中0(零)可用作滿足金融工具規(guī)范的函數(shù)參數(shù)。

      例如,當(dāng)前交易品種的移動平均線技術(shù)指標(biāo)的值可能被要求如下:

      AlligatorJawsBuffer[i]=iMA(0,0,13,8,MODE_SMMA,PRICE_MEDIAN,i);    // incorrect
      

      在新的編譯器中您應(yīng)該明確地指定NULL來規(guī)定當(dāng)前的交易品種:

      AlligatorJawsBuffer[i]=iMA(NULL,0,13,8,MODE_SMMA,PRICE_MEDIAN,i); // correct

      此外,當(dāng)前交易品種和圖表周期可使用Symbol()Period()函數(shù)來指定。

      AlligatorJawsBuffer[i]=iMA(Symbol(),Period(),13,8,MODE_SMMA,PRICE_MEDIAN,i); // correct


      2.4. Unicode字符串和它們在DLL中的使用

      字符串現(xiàn)在表示為Unicode字符序列。

      記住這一點(diǎn),并使用適當(dāng)?shù)腤indows函數(shù)。例如,使用wininet.dll庫來替代 InternetOpenA() 和InternetOpenUrlA(),您應(yīng)該調(diào)用InternetOpenW() 和InternetOpenUrlW()。

      字符串的內(nèi)部結(jié)構(gòu)在MQL4中(現(xiàn)在只需要12個字節(jié))發(fā)生了變化,當(dāng)傳遞字符串到DLL時應(yīng)使用MqlString結(jié)構(gòu):

      #pragma pack(push,1)
      struct MqlString
        {
         int      size;       // 32 bit integer, contains the size of the buffer allocated for the string
         LPWSTR   buffer;     // 32 bit address of the buffer that contains the string
         int      reserved;   // 32 bit integer, reserved, do not use
        };
      #pragma pack(pop,1)


      2.5. 文件共享

      在新MQL4中,F(xiàn)ILE_SHARE_WRITE和FILE_SHARE_READ標(biāo)志應(yīng)明確地指定以便打開文件時共享使用。 

      如果標(biāo)志不存在,那么該文件以單獨(dú)模式打開,直到文件由打開它的用戶關(guān)閉才可以被其他人打開。

      例如,使用離線圖表時共享標(biāo)志應(yīng)明確指定:

         // 1-st change - add share flags
         ExtHandle=FileOpenHistory(c_symbol+i_period+".hst",FILE_BIN|FILE_WRITE|FILE_SHARE_WRITE|FILE_SHARE_READ);

      欲了解更多詳情,請閱讀新MQL4的離線圖表。


      2.6. 日期時間轉(zhuǎn)換

      轉(zhuǎn)換日期時間為一個字符串現(xiàn)在取決于編譯模式:

        datetime date=D'2014.03.05 15:46:58';
        string str="mydate="+date;
      //--- str="mydate=1394034418" - old compiler, no directive #property strict in the new compiler
      //--- str="mydate=2014.03.05 15:46:58" - new compiler with the directive #property strict

      例如,嘗試使用文件名中包含冒號的文件會導(dǎo)致錯誤。


      3. 編譯器警告

      編譯器警告是信息性而非錯誤的訊息,但它們指出了可能的錯誤來源。

      一個清晰的代碼不應(yīng)該包含警告。


      3.1. 全局和局部變量名稱一致

      如果全局和局部各級變量具有相似的名稱:

      int i; // a global variable
      void OnStart()
        {
      //---
         int i=0,j=0; // local variables
         for (i=0; i<5; i++) {j+=i;}
         PrintFormat("i=%d, j=%d",i,j);
        }

      編譯器會顯示指出全局變量的聲明行號的警告:

      圖13. 警告“declaration of '%' hides global declaration at line %(聲明'%'隱藏在行%的全局聲明)”

      圖13. 警告“declaration of '%' hides global declaration at line %(聲明'%'隱藏在行%的全局聲明)”

      要解決這樣的警告需要修正全局變量的名稱。


      3.2. 類型不匹配

      新的編譯器有一個新的類型轉(zhuǎn)換操作。

      #property strict
      void OnStart()
        {
         double a=7;
         float b=a;
         int c=b;
         string str=c;
         Print(c);
        }

      在嚴(yán)謹(jǐn)?shù)木幾g模式下如果類型不匹配則編譯器會顯示警告:

      Figure 14. Warnings "possible loss of data due to type conversion" and "implicit conversion from 'number' to 'string'

      圖14. 警告“possible loss of data due to type conversion(由于類型轉(zhuǎn)換可能丟失數(shù)據(jù))”和“implicit conversion from 'number' to 'string'(從'數(shù)字'到'字符串'的隱式轉(zhuǎn)換)”

      在這個示例中,編譯器警告關(guān)于分配的不同數(shù)據(jù)類型的可能的精確度損失和從整數(shù)到字符串的隱式轉(zhuǎn)換。

      要解決此警告需要使用明確的類型轉(zhuǎn)換:

      #property strict
      void OnStart()
        {
         double a=7;
         float b=(float)a;
         int c=(int)b;
         string str=(string)c;
         Print(c);
        }

      3.3. 未使用的變量

      程序代碼中存在不使用的變量(多余的實(shí)體)不是一個好習(xí)慣。

      void OnStart()
        {
         int i,j=10,k,l,m,n2=1;
         for(i=0; i<5; i++) {j+=i;}
        }

      無論何種編譯模式都會顯示這些變量的報告:

      圖15. 警告“variable '%' not used('%'變量未使用)”

      圖15. 警告“variable '%' not used('%'變量未使用)”

      要修復(fù)它,需要從代碼中移除未使用的變量。


      結(jié)論

      本文描述了包含錯誤的舊程序的編譯過程中可能出現(xiàn)的常見問題。

      在所有情況下,建議使用嚴(yán)謹(jǐn)?shù)木幾g模式來調(diào)試程序。

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多