Редкий "invalid pointer access"

 

слегка грешу на новые билды,

советник который работал весьма долго начал раз в несколько дней падать.

причём в таком месте, где падать нечему..

// получить статистику отдельного символа
// если записи такй нет, то будет сделана новая
PositionStat *GetPositionStat(string symbol)
{
   int id=-1;
   int zero=-1;
   for(id=ArraySize(STAT)-1;id>=0;id--) {
      if (STAT[id]==NULL) {
         zero=id;
         continue;
      }
      if (STAT[id].symbol==symbol) break;
   }
   if (id==-1) {
      // не нашли статистику - надо делать новую
      if (zero!=-1) id=zero;
      else {
         id=ArraySize(STAT);
         ArrayResize(STAT,id+1);
      }
      STAT[id]=new PositionStat(symbol);
   }
   return STAT[id];
}
void ClearStat()
{
   for(int pos=ArraySize(STAT)-1;pos>=0;pos--) {
      if (STAT[pos]==NULL) continue;
      STAT[pos].Clear();        /// <-------- вот тут иногда падает с invalid pointer access
   }
}

в OnInit() - массив обнуляется ArrayResize(STAT,0)

элементы НИКОГДА не удаляются.

или у кого-нить возможно есть идеи как "поймать" причину ???

 
Maxim Kuznetsov:

элементы НИКОГДА не удаляются.

Если никогда не удаляются, то этот кусок кода лишний.

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Редкий "invalid pointer access"

Maxim Kuznetsov, 2022.01.27 16:15

// получить статистику отдельного символа
// если записи такй нет, то будет сделана новая
PositionStat *GetPositionStat(string symbol)
{
   int id=-1;
   int zero=-1;
   for(id=ArraySize(STAT)-1;id>=0;id--) {
      if (STAT[id]==NULL) {
         zero=id;
         continue;
      }
      if (STAT[id].symbol==symbol) break;
   }
   if (id==-1) {
      // не нашли статистику - надо делать новую
      if (zero!=-1) id=zero;
      else {
         id=ArraySize(STAT);
         ArrayResize(STAT,id+1);
      }
      STAT[id]=new PositionStat(symbol);
   }
   return STAT[id];
}
void ClearStat()
{
   for(int pos=ArraySize(STAT)-1;pos>=0;pos--) {
      if (STAT[pos]==NULL) continue;
      STAT[pos].Clear();        /// <-------- вот тут иногда падает с invalid pointer access
   }
}

или у кого-нить возможно есть идеи как "поймать" причину ???

  • В "лишние" куски вставить алерты срабатывания. Сработают - надо искать причину.
  • Поставить алерт (DebugBreak) на случай, если указатель не NULL, но при этом CheckPointer возвращает POINTER_INVALID.
  • Поставить проверку на корректность выполнения ArrayResize - маловероятно, но бывает.
  • В PositionStat прописать static-счетчик объектов, которому делать инкремент в конструкторе. Сравнивать это значение с размером STAT[]. Расхождения - алерт.
 
Maxim Kuznetsov:

слегка грешу на новые билды,

советник который работал весьма долго начал раз в несколько дней падать.

причём в таком месте, где падать нечему..

в OnInit() - массив обнуляется ArrayResize(STAT,0)

элементы НИКОГДА не удаляются.

или у кого-нить возможно есть идеи как "поймать" причину ???

А если ArrayResize вернёт -1 ?
 
Maxim Kuznetsov:

слегка грешу на новые билды,

советник который работал весьма долго начал раз в несколько дней падать.

причём в таком месте, где падать нечему..

в OnInit() - массив обнуляется ArrayResize(STAT,0)

элементы НИКОГДА не удаляются.

или у кого-нить возможно есть идеи как "поймать" причину ???


Я бы для начала убедился, что поинтер действительно invalid и в какой это позиции:

void ClearStat()
{
   for(int pos=ArraySize(STAT)-1;pos>=0;pos--) {
      if (STAT[pos]==NULL) continue;
      //--
      if(CheckPointer(STAT[pos])==POINTER_INVALID) {
         PrintFormat("POINTER_INVALID! STAT[%i]",pos);
      }
      //--
      STAT[pos].Clear();        /// <-------- вот тут иногда падает с invalid pointer access
   }
}


PS. Кстати, STAT - это массив или класс с перегруженной операцией [] ?

 
PapaYozh #:


Я бы для начала убедился, что поинтер действительно invalid и в какой это позиции:


PS. Кстати, STAT - это массив или класс с перегруженной операцией [] ?

STAT[] - это массив указателей на объекты

// класс для суммирования данных по отдельным символам
class PositionStat {
public: 
   PositionStat(string _symbol) {
      symbol=_symbol;
      Clear();
   }
   ~PositionStat() {
   }
   void Clear() {
      convers="";
      convers_op=0;
      count[0]=count[1]=0;
      lots[0]=lots[1]=0;
      profit[0]=profit[1]=0;
      swap[0]=swap[1]=0;
      weight[0]=weight[1]=0;
      price[0]=price[1]=0;
   }
   string symbol;    // имя символа
   string convers;   // как конвертировать залог
   int convers_op;
   int count[2];     // число позиций покупка/продажа
   double lots[2];   // суммарный объем 
   double profit[2];
   double swap[2];
   double weight[2]; // сумма весов (лот*цена)
   double price[2];  // средняя цена позиций
};   

PositionStat *STAT[];   // тут будем хранить все записи по символам

пока-что поставил CheckPointer и запись в отдельный файл если неправильный указатель. Просто Print явно не обойтись - ошибка редкая, потом в журнале не найдёшь такую запись

 
Maxim Kuznetsov #:

STAT[] - это массив указателей на объекты

пока-что поставил CheckPointer и запись в отдельный файл если неправильный указатель. Просто Print явно не обойтись - ошибка редкая, потом в журнале не найдёшь такую запись

Правильно. CheckPointer  как раз решит проблему. Скорее всего, где-то есть удаление объекта без последующего обнуления указателя. Вот и получаем Invalid pointer.

 

Еще есть один стандартный случай так вляпаться.

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

 
for(int pos=ArraySize(STAT)-1;pos>=0;pos--) {

Некошерно. 

 
Vladimir Simakov #:

Еще есть один стандартный случай так вляпаться.

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

Чего?