Почему пропадает указатель?

 

Добрый день.

Не могу разобраться:

В самом начале выполнения программы есть конструктор Expert():

#include "Expert.mqh"
Expert gExpert = Expert();

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
  if (gExpert.Init() == true){
      return INIT_SUCCEEDED; 
      }
  else{
    return INIT_FAILED; 
    }
  }

в нем передается указатель в объект ex_Trade:

ex_ParametersStatistical = ParametersStatistical();                                     
  
ex_Trade                 = Trade(aMagic, GetPointer(ex_ParametersStatistical));

Всё заполнилось:


но когда выходим из конструктора Expert(), заходим в OnInit() и проваливаемся gExpert.Init(), указатель в объекте ex_Trade уже Invalid:


Почему?
 

Доброе время суток!

Навскидку отвечу.

Попробуйте так:

#include "Expert.mqh"
Expert gExpert;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
  gExpert = Expert();
  if (gExpert.Init() == true){
      return INIT_SUCCEEDED; 
      }
  else{
    return INIT_FAILED; 
    }
  }

Или так:

#include "Expert.mqh"
Expert *gExpert;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
  gExpert new = Expert();
  if (gExpert.Init() == true){
      return INIT_SUCCEEDED; 
      }
  else{
    return INIT_FAILED; 
    }
  }
 
Igor Zakharev:

Доброе время суток!

Навскидку отвечу.

Попробуйте так:

Или так:


Попробовал первый вариант - перенес  "gExpert = Expert()" в OnInit  - не помогло.

 
В конструкторе Expert, Вы создаёте локальный объект ex_ParametersStatistical.
Сохраняете адрес этого объекта.
Но при выходе из конструктора объект уничтожается.
Поэтому адрес становится недействительным.

 
Nextor:


Попробовал первый вариант - перенес  "gExpert = Expert()" в OnInit  - не помогло.

Я наверное спросони опечатался и new до равно поставил, но думаю вы идею поняли, попробуйте вот это:
#include "Expert.mqh"
Expert *gExpert;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
  gExpert = new Expert();
  if (gExpert.Init() == true){
      return INIT_SUCCEEDED; 
      }
  else{
    return INIT_FAILED; 
    }
  }
 
Igor Zakharev:
Я наверное спросони опечатался и new до равно поставил, но думаю вы идею поняли, попробуйте вот это:
Не хочу плодить указатели без повода. Expert должен быть объектом, не указателем.
 
Koldun Zloy:
В конструкторе Expert, Вы создаёте локальный объект ex_ParametersStatistical.
Сохраняете адрес этого объекта.
Но при выходе из конструктора объект уничтожается.
Поэтому адрес становится недействительным.

Спасибо.
Было похоже на правду.
Даже написал скрипт, чтоб проверить, но увы, скрипт опроверг вашу идею.
В нем указатель на объект Alfa создается в конструкторе gGamma, но по выходу из конструктора указатель не пропадает и код в функции OnStart нормально отрабатывает:

//+------------------------------------------------------------------+
//|                                                  TestPointer.mq5 |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
   
class Alfa
   {
   private:  
      int a;
   public:
         Alfa(){a = 10;};
         ~Alfa(){};
    void SetA(int aValue){a = aValue;};
   };
   
class Betta
   {
   private:  
      Alfa * bt_Alfa;
   public:
         Betta(){};
         Betta(Alfa * aAlfa){bt_Alfa = aAlfa;};
         ~Betta(){};
    void SetA(int aValue){bt_Alfa.SetA(aValue);};
   };   
 
class Gamma
   {
   private:  
      Alfa  gm_Alfa;
      Betta gm_Betta;
   public:
      Gamma(){gm_Betta = Betta(GetPointer(gGamma.gm_Alfa));};
      ~Gamma(){};
      void Test1() {gm_Alfa.SetA(100);};
      void Test2() {gm_Alfa.SetA(300);};
      void Test3() {gm_Betta.SetA(1000);};
   };
//--------------------------------------------------------------
//---В конструкторе gGamma создаем указатель на gGamma.gm_Alfa
//---и передаем указатель в конструктор Betta 
//--------------------------------------------------------------
Alfa  gAlfa  = Alfa();  
Betta gBetta = Betta(); 
Gamma gGamma = Gamma();
//-------------------------------------------------------------
//---Во всех функциях ниже указатель на gGamma.gm_Alfa доступен:
//-------------------------------------------------------------  
void OnStart()
  {
  gGamma.Test1();
  gGamma.Test2();
  gGamma.Test3();
  int stop = 1;
  }



Файлы:
 
Это не идея, а правда. Я никогда не говорю наугад.
У Вас ex_ParametersStatistical не указатель, а объект.
Это хорошо видно по Вашим скриншотам из отладчика.
Хотя правильнее было бы попросить Вас привести полный код.
Или хотя бы конструктор Expert() и функцию ParametersStatistical().

 
Koldun Zloy:
Это не идея, а правда. Я никогда не говорю наугад.
У Вас ex_ParametersStatistical не указатель, а объект.
Это хорошо видно по Вашим скриншотам из отладчика.
Хотя правильнее было бы попросить Вас привести полный код.
Или хотя бы конструктор Expert() и функцию ParametersStatistical().

Именно!:
ex_ParametersStatistical объект класса Expert
ex_Trade - тоже обект класса Expert

class Expert
  {
private:
   
   string                  ex_Code;
   string                  ex_ExpertName;
   
   datetime                ex_PeriodStartHistoryPass;
   datetime                ex_PeriodEndHistoryPass;
   
   int                     ex_HandleZZ_1;
   double                  ex_BufferZZ_1Main[];
   double                  ex_BufferZZ_1Highs[];
   double                  ex_BufferZZ_1Lows[];
   datetime                ex_BufferDates[];
   double                  ex_BufferHighs[];
   double                  ex_BufferLows[];
   
   ManagerCCI              ex_ManagerCCI;
   ManagerPositions        ex_ManagerPositions[];
   ManagerTradeObjects     ex_ManagerTradeObjects;
   ParametersStatistical   ex_ParametersStatistical;
   Trade                   ex_Trade;
   
   Display                 ex_Display;


Задача  - передать объект ex_ParametersStatistical объекту ex_Trade.
Поэтому, в конструкторе класса Expert создается объект ex_ParametersStatistical, и указатель на него передаётся в конструктор объекта ex_Trade.
И всё отрабатывает хорошо, до момента выхода из конструктора Expert.

В скрипте выше аналогичный пример - там все отрабатывается, хотя указатель тоже создается в конструкторе объекта.

Итак, вот вам конструктор Expert:

Expert::Expert(string aCode, string aName, int aMagic, double aLot, int aZZDepth_1, int aZZDeviation_1, int aZZBackstep_1, double aProfit, double aMinRange,
               bool aDisplayExpert, bool aDisplayManagerCCI, bool aDisplayManagerPositions, bool aDisplayManagerPositionsArray, bool aDisplayManagerTradeObjectsArray, 
               bool aDisplayParametersStatistical, bool aDisplayTrade, bool aWriteOnTesterResults):
                     ex_Code(aCode),
                     ex_ExpertName(aName),
                     ex_Magic(aMagic),
                     ex_Lot(aLot),
                     ex_ZZDepth_1(aZZDepth_1),
                     ex_ZZDeviation_1(aZZDeviation_1),
                     ex_ZZBackstep_1(aZZBackstep_1),
                     ex_Profit(aProfit),
                     ex_MinRange(aMinRange),
                     ex_DisplayExpert(aDisplayExpert),
                     ex_DisplayManagerCCI(aDisplayManagerCCI),
                     ex_DisplayManagerPositions(aDisplayManagerPositions),
                     ex_DisplayManagerPositionsArray(aDisplayManagerPositionsArray),
                     ex_DisplayManagerTradeObjectsArray(aDisplayManagerTradeObjectsArray),
                     ex_DisplayParametersStatistical(aDisplayParametersStatistical),
                     ex_DisplayTrade(aDisplayTrade),
                     ex_WriteOnTesterResults(aWriteOnTesterResults)
                     
  { 
  ex_ManagerCCI            = ManagerCCI("01","ManagerCCI",iDisplayManagerCCI,iPeriodCCI,iLevelCCI1,iLevelCCI2);
  
  ex_QtyManagerPos         = 2;
  ArrayResize(ex_ManagerPositions,ex_QtyManagerPos);
  ex_ManagerPositions[0]   = ManagerPositions("01","ManagerPositions","Buy",iDisplayManagerPositions, iDisplayManagerPositionsArray, aMagic);
  ex_ManagerPositions[1]   = ManagerPositions("02","ManagerPositions","Sell",iDisplayManagerPositions, iDisplayManagerPositionsArray, aMagic);

  
  ex_ManagerTradeObjects   = ManagerTradeObjects();
  ex_ParametersStatistical = ParametersStatistical("01","ParametersStatistical",iDisplayParametersStatistical);
  
  ex_Trade                 = Trade(aMagic, GetPointer(ex_ParametersStatistical));
  ex_Display               = Display(ex_Code, ex_Code + " " + ex_ExpertName);
  }

Вот конструктор PrametersStatistical:

ParametersStatistical ::ParametersStatistical(string aCode, string aName, bool aToDisplayParametersStatistical):
                        ps_Code(aCode),
                        ps_Name(aName),
                        ps_ToDisplayParametersStatistical(aToDisplayParametersStatistical),
                        ps_QtyLabels(0),
                        ps_MaxLotBuy(0.0),
                        ps_MaxLotSell(0.0),
                        ps_MinAccountEquity(AccountInfoDouble(ACCOUNT_EQUITY)),
                        ps_MinAccountBalance(AccountInfoDouble(ACCOUNT_BALANCE)),
                        ps_MaxAccountBalance(0.0),
                        ps_MinAccountMarginLevel(AccountInfoDouble(ACCOUNT_MARGIN_FREE)),
                        ps_QtyPositionsBuy(0),
                        ps_QtyPositionsSell(0),
                        ps_QtyOfCallPositionsCloseBuy(0),
                        ps_QtyOfCallPositionsCloseSell(0),
                        ps_AverageQtyPositionsBuyInTheNet(0.0),
                        ps_AverageQtyPositionsSellInTheNet(0.0)
  {
  ps_Display = Display(ps_Code, ps_Code + " " + ps_Name);
  }

вот класс ex_Trade и его конструкторы:

class Trade
  {
private:

   int                     tr_Magic;
   int                     tr_Deviation;
   CTrade                  tr_Trade;
   ParametersStatistical   * tr_ParametersStatistical;
   
public:
                     Trade();
                     Trade(int aMagic, ParametersStatistical * aParametersStatistical);
                    ~Trade();
               bool Init(void);
               void PositionsUpdate(void);
               bool PositionOpen(ENUM_ORDER_TYPE aOrderType, double aLot, MqlTradeResult & aResult, double aSl = 0.0, double aTp = 0.0, string aComment = "");
               bool PositionsClose();
               bool PositionsClose(string aTypePos);
               bool PositionClose(ulong aTicket);
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
Trade::Trade()
  {
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
Trade::Trade(int aMagic, ParametersStatistical * aParametersStatistical)
  {
  tr_Magic = aMagic;
  tr_ParametersStatistical = aParametersStatistical;  //По выходу из конструктора Expert, этот указатель не сохраняется
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
Trade::~Trade()
  {
  delete tr_ParametersStatistical;
  }
 

Попробовал Ваш код. Всё работает нормально. Возможно отладчик неправильно показывает.

И Вам нужно разобраться с удалением tr_ParametersStatistical.

Так как делаете Вы делать нельзя.

Или уберите 

delete tr_ParametersStatistical;

Или создавайте его динамически( через new ).

Но тогда удалять лучше в деструкторе класса Expert.

Причина обращения: