Как запустить проход оптимизации с определённым номером?

 

Всех приветствую. 

У меня в коде появилась странная "плавающая" ошибка, которую я никак не могу вычислить. 

На НЕКОТОРЫХ проходах в лог выходит сообщение:

genetic pass (38, 476) tested with error "critical runtime error 502 in OnTester function (array out of range, module Experts\MyExperts\TRBreak\TRBreakS.ex5, file TSBuffers.mq5, line 50, col 21)" 

Как видно - обращение за пределы массива. 

Надо понять, как это происходит, а для этого - запустить этот самый  "genetic pass (38, 476)" в отладчике. Вопрос - как это сделать? 

Дополнительная информация:

Собственно, код, где происходит ошибка:


#ifdef _CHECK_CMYPRICEBUFFER_ACCESS_

double CMyPriceBuffer::GetAt(const uint uiIdx) const
{ 
   // Проверим входной индекс на соответствие размеру массива
   // Возвратим элемент, если всё в порядке
   if((int)uiIdx < Total() && (int)uiIdx < ArraySize(m_data)) 
      return(m_data[uiIdx]);                                                    /// ЗДЕСЬ ПРОИСХОДИТ ОШИБКА ОБРАЩЕНИЯ К МАССИВУ
   
   // Элемент массива не существует!
   // Возвращаем сообщение
   Print("ВНИМАНИЕ ! Запрос несуществующего элемента массива! uiIdx = " + IntegerToString(uiIdx) + "; Total() = " + IntegerToString(Total()) + "; ArraySize() = " + IntegerToString(ArraySize(m_data)));
   
   // Прекращаем работу эксперта.         
   ASSERT(false); 
   int iCheckValue = _CHECK_CMYPRICEBUFFER_ACCESS_;
   if(iCheckValue == NULL)
      {
      Print("ВНИМАНИЕ ! Определён нулевой дефайн _CHECK_CMYPRICEBUFFER_ACCESS_. Вызываем ExpertRemove().");
      ExpertRemove();
      };
      
   return(EMPTY_VALUE); 
};
 
#endif // _CHECK_CMYPRICEBUFFER_ACCESS_


Класс CMyPriceBuffer объявлен, как наследник стандартного массива:

CMyPriceBuffer: public CArrayDouble;

Даже ввел специальный дефайн _CHECK_CMYPRICEBUFFER_ACCESS_, который позволяет перегрузить функцию GetAt().

И непонятно, почему ИНОГДА происходит выход за пределы массива, при том, что я размер массива проверяю уж и на Total(), и на ArraySize() - исходя из кода - никак не может быть выход за пределы... Даже если я подаю индекс за пределами - должно возвращаться значение EMPTY_VALUE...  А поди ж ты... 

Собственно, оттуда и вопрос - как запустить эксперта именно по указанному проходу? 
 

Ну если адекватные проверки не помогают, то нужно проверить не адекватные)))

Я бы проверил на  uiIdx < 0, так как  uint не гарантирует, что значение  uiIdx обязательно будет положительным.

uint uiIdx = -1;
int sss = (int)uiIdx; // -1
 
Aleksandr Slavskii #:

Ну если адекватные проверки не помогают, то нужно проверить не адекватные)))

Я бы проверил на  uiIdx < 0, так как  uint не гарантирует, что значение  uiIdx обязательно будет положительным.

В коде там есть эта проверка, причём как на Total(), так и на непосредственно ArraySize().

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

Странно также, что ситуация происходит нечасто. 

Поэтому я и хочу запустить проверку именно с теми параметрами, что были в указанном проходе... 

Пока у меня идея заменить непосредственное обращение к элементу обращением через функцию базового класса At(). Подозрение, что проблема в ошибках оптимизации при компиляции. Посмотрим, поможет ли. 
 
Georgiy Merts:
Надо понять, как это происходит, а для этого - запустить этот самый  "genetic pass (38, 476)" в отладчике. Вопрос - как это сделать? 

Если в таблице оптимизации после отключения всех фильтров этот проход есть, то - по клику на нем.

 
Ivan Titov #:

Если в таблице оптимизации после отключения всех фильтров этот проход есть, то - по клику на нем.

Хм... Интересно, надо поглядеть, когда ошибка "вылезет" (она, как я уже говорил, "плавающая")... А то ищу, блин, вчерашний день...  

 
Georgiy Merts #:

В коде там есть эта проверка, причём как на Total(), так и на непосредственно ArraySize().

Я вот про такую проверку говорю

if((int)uiIdx < Total() && (int)uiIdx < ArraySize(m_data) && (int)uiIdx >= 0)
   return(m_data[uiIdx]);

Если проход сохранится, то тогда конечно можно его прогнать и .... А всё равно придётся как то вылавливать ошибку)))

 
Georgiy Merts:

genetic pass (38, 476) tested with error "critical runtime error 502 in OnTester function (array out of range, module Experts\MyExperts\TRBreak\TRBreakS.ex5, file TSBuffers.mq5, line 50, col 21)" 

Сталкиваюсь с таким, когда не хватает памяти.

Надо понять, как это происходит, а для этого - запустить этот самый  "genetic pass (38, 476)" в отладчике. Вопрос - как это сделать? 

К сожалению, в opt-формате, вроде, нет этих данных. Поэтому идентифицировать проход без изменений в коде не получится, видимо.


Попробуйте в OnInit создавать Common-файл (имя файла генерировать индивидуально для каждого набора) с набором входных, а в OnDeinit - удалять его. Тогда оставшиеся файлы после оптимизации - неудачные проходы.

 
fxsaber #:

Сталкиваюсь с таким, когда не хватает памяти.

К сожалению, в opt-формате, вроде, нет этих данных. Поэтому идентифицировать проход без изменений в коде не получится, видимо.


Попробуйте в OnInit создавать Common-файл (имя файла генерировать индивидуально для каждого набора) с набором входных, а в OnDeinit - удалять его. Тогда оставшиеся файлы после оптимизации - неудачные проходы.

Хм... Хорошая мысль,  fxsaber. 

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

 
Aleksandr Slavskii #:

Я вот про такую проверку говорю

Если проход сохранится, то тогда конечно можно его прогнать и .... А всё равно придётся как то вылавливать ошибку)))

Да, есть вариант, что  происходит переполнение при преобразовании типов (если на вход передаётся UINT_MAX, и оно преобразуется в int = -1), так что, я добавлю такую проверку. Посмотрим.