Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам - страница 600

 
Vasiliy Sokolov:

Здесь не клуб телепатов. Свой код Вы не приложили, поэтому о том, где размещать delete, думайте сами.

Неправильно. 

Так вот же показал код, что еще надо? Как правильно, если неправильно? 

Спасибо.

 
Artyom Trishkin:

Эк вы всё позапутали. Не правильное планирование задачи как раз и приводит к таким вот последствиям.

Если объекты создаются в классе, то по завершении его работы он должен их удалить в своём деструкторе. Другие же классы, прежде чем получить указатель на объект, должны проверить его валидность. И в принципе не должно быть таких переплетённых взаимосвязей. Клубок наплели какой-то. Сложно - не означает качественно. Всё должно быть прозрачно и отслеживаемо. В первую же очередь - для вас.

Давайте лучше будет показать код.

Вот я на старте программы считываю некоторые данные из файла.

CCandlesOneRules candles_one_rules;

while(!FileIsEnding(file_handle))
     {
      CCandleCondition *candle_cond=new CCandleCondition();
      string_num++;      
      string str=FileReadString(file_handle);
      int len=StringLen(str);
      if(len<=0)
         continue;
      string cand_num_str="";
      string rule_str="";
      string rule_descr="";
      string shift_str="";
      string value_int_str="";
      string value_enum_str="";
      string status_str="";
      int start_ind=0;
      int status_ind=-1;
      //--- status
      for(int i=start_ind;i<len;i++)
        {
         ushort ch=StringGetCharacter(str,i);
         if(ch==Separator)
           {
            start_ind=i+1;
            break;
           }
         status_str+=CharToString((uchar)ch);
         status_ind=i;
        }      
      int status=(int)StringToInteger(status_str);
      if(!init_flag && status!=0)
         continue;
      //--- candle number
      for(int i=start_ind;i<len;i++)
        {
         ushort ch=StringGetCharacter(str,i);
         if(ch==Separator)
           {
            start_ind=i+1;
            break;
           }
         cand_num_str+=CharToString((uchar)ch);
        }      
      //--- rule    
      for(int i=start_ind;i<len;i++)
        {
         ushort ch=StringGetCharacter(str,i);
         if(ch==Separator)
           {
            start_ind=i+1;
            break;
           }
         rule_str+=CharToString((uchar)ch);
        }
      //--- shift
      for(int i=start_ind;i<len;i++)
        {
         ushort ch=StringGetCharacter(str,i);
         if(ch==Separator)
           {
            start_ind=i+1;
            break;
           }
         shift_str+=CharToString((uchar)ch);
        }
      //--- value
      for(int i=start_ind;i<len;i++)
        {
         ushort ch=StringGetCharacter(str,i);
         if(ch==Separator)
           {
            start_ind=i+1;
            break;
           }
         value_int_str+=CharToString((uchar)ch);
        }
      //--- rule description
      for(int i=start_ind;i<len;i++)
        {
         ushort ch=StringGetCharacter(str,i);
         if(ch==Separator)
           {
            start_ind=i+1;
            break;
           }
         rule_descr+=CharToString((uchar)ch);
        }
      //--- enum value 
      for(int i=start_ind;i<len;i++)
        {
         ushort ch=StringGetCharacter(str,i);
         if(ch==Separator)
           {
            start_ind=i+1;
            break;
           }
         value_enum_str+=CharToString((uchar)ch);
        }                  
      int candN=(int)StringToInteger(cand_num_str);
      int ruleN=(int)StringToInteger(rule_str);
      int shift=(int)StringToInteger(shift_str);
      candle_cond.Create(candN,ruleN,shift,value_int_str,rule_descr);
      if(CheckPointer(candle_cond))
        {
         if(candles_one_rules.AddCondition(GetPointer(candle_cond)))
           {
            if(StringToInteger(value_int_str)>0)
              {
               Print(__FUNCTION__+": candle one #: ",candle_cond.GetCandNumber(),", rule: ",candle_cond.GetRuleNumber(),", shift: ",candle_cond.GetShift(),", description: ",candle_cond.GetDescription(),", value: ",candle_cond.GetValueStr());
              }
            Print(__FUNCTION__+": size of condition: ",sizeof(candle_cond));
           }           
        }
     ...
    } 

То есть, на итерации создаю объект CCandleCondition *candle_cond, а затем добавляю его в коллекцию candles_one_rules.

Вот у метод AddCondition класса CCandlesOneRules:

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool CCandlesOneRules::AddCondition(CCandleCondition *cond)
  {
   for(int i=0;i<Total();i++)
     {
      CCandleOneRules *candle_one_r=At(i);
      if(!CheckPointer(candle_one_r))
         continue;
      if(cond.GetCandNumber()!=candle_one_r.GetCandOneNumber())
         continue;
//--- if candle one rules object with the same candle one number as the new condition is found         
      for(int j=0;j<candle_one_r.Total();j++)
        {
         CCandleRule *candle_rule=candle_one_r.At(j);
         if(!CheckPointer(candle_rule))
            continue;            
         if(candle_rule.GetRuleNumber()!=cond.GetRuleNumber())
            continue;
//--- if candle rule with the same rule number as the new condition is found            
         for(int k=0;k<candle_rule.Total();k++)         
           {
            CCandleCondition *rule_cond=candle_rule.At(k);
            if(!CheckPointer(rule_cond))
               continue;
            if(rule_cond.GetShift()!=cond.GetShift())
               continue;
//--- if rule condition with the same shift as the new condition is found
//--- update rule condition               
            return candle_rule.Update(k,GetPointer(cond));
           }
//--- if rule condition with the same shift as the new condition not found
//--- add the new condition
         return candle_rule.Add(GetPointer(cond));
        }
//--- if rule with the same rule number as the new condition not found        
//--- create new rule
      CCandleRule *new_rule=new CCandleRule(cond.GetCandNumber(),cond.GetRuleNumber());
      new_rule.Add(GetPointer(cond));
      return candle_one_r.Add(GetPointer(new_rule));
     }
//--- if candle one rules object with the same candle one number as the new condition not found
//--- create new candle one rule object
   if(cond.GetCandNumber()>m_candles_one_total)
      m_candles_one_total=cond.GetCandNumber();
   CCandleOneRules *new_cand_one_r=new CCandleOneRules(cond.GetCandNumber());
   CCandleRule *new_rule=new CCandleRule(cond.GetCandNumber(),cond.GetRuleNumber());
   new_rule.Add(GetPointer(cond));
   new_cand_one_r.Add(GetPointer(new_rule));
   return Add(GetPointer(new_cand_one_r));
//--- 
  }

CCandleRule это просто класс-контейнер для conditions. Условия я добавляю в правила, а правила в CCandleOneRules, которые в свою очередь в CCandlesOneRules....

Вот этот цикл while на старте не проходит, вылетает с ошибкой out of memory. Причем там не особо много этих условий, всего 7 до остановки считывается. Если снизить число данных в читаемом файле, то работает, без всяких ошибок undeleted objects и прочее. 

 
Прошу прощения. Количество объектов CCandleCondition (простой класс, наследуемый от CObject) 91831. После этого out of memory.
 
Juer:

Давайте лучше будет показать код.

Я начинаю терять терпение.

new_cand_one_r.Add(GetPointer(new_rule));
return Add(GetPointer(new_cand_one_r));

Где определение метода Add? 

Судя по коду у Вас полное не понимание того, что Вы делаете.

 
Vasiliy Sokolov:

Я начинаю терять терпение.

Где определение метода Add? 

Судя по коду у Вас полное не понимание того, что Вы делаете.

CCandleOneRules, CCandlesOneRules, CCandleRule всё классы, наследумые от CArrayObj.

Судя по вашим общим ответам, вы просто не понимаете мои вопросы. По массиву с CArrayObj вы так и не ответили, как правильно. Ещё раз повторю ту задачу. Есть класс, в методе класса глобальные объекты класса добавляются в массив (объект типа CArrayObj), который объявляется там же в этом методе. В данном методе производятся в этом массиве некоторые действия. По завершении, объект-массив не нужен, члены массива нужны. Как правильно избавиться от этого объекта-массива, сохранив члены массива? Если не избавиться от него, то в логе получим сообщения вида undeleted objects. Я привел своё решение, вы сказали неправильно. Как правильно? Как я могу разместить delete в OnDeinit (либо в Deinit методе класса, который будет вызываться из OnDeinit), если данный объект-массив виден только в пределах метода класса?

Более того, если объекты удалять только в OnDeinit, в процессе выполнения программы/тестирования можно так же нарваться на out of memory...

 

Здравствуйте, коллеги.

Помогите разобраться с таким вопросом. Где рациональнее всего использовать функцию ArraySetAsSeries() для указания порядка нумерации элементов индикаторного буфера? В предустановленных в терминал индикаторах часто наблюдал, что её используют внутри OnCalculate(). Но индикаторный буфер объявляется глобально. Не логично ли в этом случае единожды использовать ArraySetAsSeries() внутри функции OnInit() для однократного вызова? Или из-за пополнения индикаторного буфера новыми элементами может слететь порядок нумерации и есть необходимость обращаться к ArraySetAsSeries() каждый раз внутри OnCalculate()? Хочется написать оптимальный код, где нет лишних вызовов функций, когда это не нужно. Буду благодарен за помощь.

 
Oleg Remizov:

Здравствуйте, коллеги.

Помогите разобраться с таким вопросом. Где рациональнее всего использовать функцию ArraySetAsSeries() для указания порядка нумерации элементов индикаторного буфера? В предустановленных в терминал индикаторах часто наблюдал, что её используют внутри OnCalculate(). Но индикаторный буфер объявляется глобально. Не логично ли в этом случае единожды использовать ArraySetAsSeries() внутри функции OnInit() для однократного вызова? Или из-за пополнения индикаторного буфера новыми элементами может слететь порядок нумерации и есть необходимость обращаться к ArraySetAsSeries() каждый раз внутри OnCalculate()? Хочется написать оптимальный код, где нет лишних вызовов функций, когда это не нужно. Буду благодарен за помощь.

ИМХО, я бы писал индикаторы вообще без этих функций (если с нуля, конечно). А так - для буферов - в OnInit(), для таймсерий - в OnCalculate().

И, чтобы говорить об оптимальном коде, нужно знать, сколько времени выполняется эта функция. Так что, сначала должен идти профилировщик, а только потом вопросы по производительности.

 
Alexey Kozitsyn:

ИМХО, я бы писал индикаторы вообще без этих функций (если с нуля, конечно). А так - для буферов - в OnInit(), для таймсерий - в OnCalculate().

И, чтобы говорить об оптимальном коде, нужно знать, сколько времени выполняется эта функция. Так что, сначала должен идти профилировщик, а только потом вопросы по производительности.

К такому выводу и склонялся. Спасибо за подсказку.

 

Добрый день. Возник такой вопрос: почему когда накладываю полосы болинджера на MACD, берутся значения сигнальной линии, а не самой гистограммы? 

 
Виктор:

Добрый день. Возник такой вопрос: почему когда накладываю полосы болинджера на MACD, берутся значения сигнальной линии, а не самой гистограммы? 

Вы имеете возможность указывать какой графический буфер использовать для расчета?

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