Access violation write to 0x3FF3AAC7 in... - страница 2

 
Nauris Zukas:
Что за ошибка в индикаторе появилась и не как не избавится? DLL не использует.
Это ошибка компилятора, лучше предоставить информацию разработчикам для исправления
 
Renat Akhtyamov:

странно...

может быть так?

Я думал если массив double MaxMinPrice[][3] , то и всем значением надо быть double, а то будет предупреждение при компиляций. Проверил, нету предупреждение на int (странно). Спасибо, поставлю int.

 
Ihor Herasko:

Нет, не меньше (double и datetime имеют одинаковый размер), но со структурами намного удобнее и понятнее. Ведь тяжело постоянно держать в голове, какой индекс элемента массива за что отвечает. С многомерными массивами проблема усугубляется.

В Вашем случае это выглядело бы так:

Можно вопрос

struct Dot
{
   datetime    dtTime;
   double      fPrice;

   void Set(const datetime _dtTime, const double _fPrice) // зачем так?
   {
      dtTime = _dtTime;
      fPrice = _fPrice;
   }
};

Dot arrstDots[10];

//Почему так хуже.
struct Dot
{
   datetime    dtTime;
   double      fPrice;
};

Dot arrstDots[10], Arr[5];

Не догоняю зачем константные переменные в функции и зачем функция в теле структуры. Что делает функция.

 
Ihor Herasko:
При увеличении размера массива он может быть перенесен в памяти в больший кусок, когда прежнего выделенного места в памяти не хватает. При этом старый указатель на массив становится невалидным. Если используете передачу ссылок на массив, то после добавления в него данных не нужно продолжать обращаться к этому массиву по старой ссылке. То есть после добавления элемента в массив нужно вернуться в то место, где формируется ссылка на массив, и создать новую ссылку на него.

Всё таки не понятно с указателем на массив, как это мне может решить проблему. При самом заполнение массива уже access violation и даже до вызова функций не доходит. Вот сделал отдельный кусок для тестов, если M1 баров достаточна то access violation (в моем случае 43690). Попробуйте на своей платформе, если появится access violation, как вы бы переделали конкретный пример?

double MaxMinPrice[][3];
void TestArrayMemory()
  {

   int MaxMinCount=-1;
   int AllBarsM1=iBars(Symbol(),PERIOD_M1);
   int cnt=1;
   while(cnt<AllBarsM1)// && cnt<=43690)
     {
      MaxMinCount++;
      //Print(" MaxMinCount: ",MaxMinCount);
      ArrayResize(MaxMinPrice,MaxMinCount+1);
      MaxMinPrice[MaxMinCount][0]=(int)iTime(Symbol(),PERIOD_M1,cnt);
      MaxMinPrice[MaxMinCount][1]=iHigh(Symbol(),PERIOD_M1,cnt);
      MaxMinPrice[MaxMinCount][2]=iLow(Symbol(),PERIOD_M1,cnt);
      cnt++;
     }

  }
 
Nauris Zukas:

Я думал если массив double MaxMinPrice[][3] , то и всем значением надо быть double, а то будет предупреждение при компиляций. Проверил, нету предупреждение на int (странно). Спасибо, поставлю int.

В int не поместится datetime, обрежется. Не делайте так.

 
Valeriy Yastremskiy:

Можно вопрос

Не догоняю зачем константные переменные в функции

Константные переменные ускоряют выполнение кода. Доказано fxsaber.

и зачем функция в теле структуры. Что делает функция.

Функция позволяет делать код более удобочитаемым, избавляясь от портянок. Ведь даже в случае с двумя переменными удобство очевидно:

arrstDots[0].Set(dtTime, fPrice);

Вместо:

arrstDots[0].dtTime = dtTime;
arrstDots[0].fPrice = fPrice;

Что уж говорить о случаях, когда членов структуры поболее, чем 2?

 
Ihor Herasko:

Константные переменные ускоряют выполнение кода. Доказано fxsaber.

Функция позволяет делать код более удобочитаемым, избавляясь от портянок. Ведь даже в случае с двумя переменными удобство очевидно:

Вместо:

Что уж говорить о случаях, когда членов структуры поболее, чем 2?

Спасибо. Видимо по другому воспитан) В одномерных массивах до 10 переменных привязываю к одному индексу) Назначение по логике по имен. Позже видимо придется перевоспитываться.)

 
Nauris Zukas:

Всё таки не понятно с указателем на массив, как это мне может решить проблему.

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

При самом заполнение массива уже access violation и даже до вызова функций не доходит.

Да, это то, о чем я и говорил. В процессе работы с массивом ему нужно перераспределиться, а памяти для нового большого куска не хватает. Где-то нет соответствующей проверки в МТ. Потому как если сразу запросить нужный объем памяти для многомерного массива, то его не хватает:

double arrfArray[][3];
int nBars = iBars(Symbol(), PERIOD_M1);

if (ArrayResize(arrfArray, nBars) != nBars)
{
   Alert("Ошибка распределения памяти: ", GetLastError());
   return;
}

В результате выполнения этого кода при условии достаточно глубокой истории М1 (более 50000 баров) памяти не хватает.

Вот сделал отдельный кусок для тестов, если M1 баров достаточна то access violation (в моем случае 43690). Попробуйте на своей платформе, если появится access violation, как вы бы переделали конкретный пример?

Я бы сделал так (распределил память один раз):

struct Candles
{
   datetime    dtTime;
   double      fHigh;
   double      fLow;
   
   void Set(const datetime _dtTime, const double _fHigh, const double _fLow)
   {
      dtTime = _dtTime;
      fHigh = _fHigh;
      fLow = _fLow;
   }
};

Candles arrstCandles[];
 
void OnStart()
{

   int nBars = iBars(Symbol(), PERIOD_M1);

   if (ArrayResize(arrstCandles, nBars) != nBars)
   {
      Alert("Ошибка распределения памяти: ", GetLastError());
      return;
   }
   
   --nBars;
   for (int i = 0; i < nBars; ++i)
      arrstCandles[i].Set(iTime(Symbol(), PERIOD_M1, i + 1), iHigh(Symbol(), PERIOD_M1, i + 1), iLow(Symbol(), PERIOD_M1, i + 1));
}

Хотя это возможно для упрощенного примера. В боевых условиях неизвестно, сколько нужно памяти и приходится перераспределять ее время от времени. В этом случае стоит использовать третий аргумент функции ArrayResize (аргумент reserve_size).

Документация по MQL5: Операции с массивами / ArrayResize
Документация по MQL5: Операции с массивами / ArrayResize
  • www.mql5.com
ArrayResize - Операции с массивами - Справочник MQL5 - Справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Ihor Herasko:

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

Да, это то, о чем я и говорил. В процессе работы с массивом ему нужно перераспределиться, а памяти для нового большого куска не хватает. Где-то нет соответствующей проверки в МТ. Потому как если сразу запросить нужный объем памяти для многомерного массива, то его не хватает:

В результате выполнения этого кода при условии достаточно глубокой истории М1 (более 50000 баров) памяти не хватает.

Я бы сделал так (распределил память один раз):

Хотя это возможно для упрощенного примера. В боевых условиях неизвестно, сколько нужно памяти и приходится перераспределять ее время от времени. В этом случае стоит использовать третий аргумент функции ArrayResize (аргумент reserve_size).

Огромное спасибо! Впредь буду осторожнее с многомерными массивами.

 
Ihor Herasko:

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

Начал по больше использовать struct, но появилась одна задержка. Может кто подскажет, как правильно вставить struct в функцию? Массив умею вставить в функцию, но со структурой не могу разобраться.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   TestFunction(Test);
  }
//+------------------------------------------------------------------+
struct Struct
  {
   double            TestDouble;
  };
Struct Test[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void TestFunction(struct &Str[])
  {
   int CheckSize=ArraySize(Str);
   Print("-0- CheckSize: ",CheckSize);
  }


/*
TestFunction(TestDouble); // OnTick()

double  TestDouble[]={5,3,9,4};
void TestFunction(double &Str])
  {
   int CheckSize=ArraySize(Str);
   Print("-0- CheckSize: ",CheckSize);
  }
//+------------------------------------------------------------------+
*/
Причина обращения: