исключение: std::bad_alloc в ячейке памяти в цикле

#c #exception #memory-leaks #memory-management

#c #исключение #утечки памяти #управление памятью

Вопрос:

У меня проблема с выделением памяти. Но я не знаю, в чем проблема

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

Сегмент кода, в котором возникает ошибка (весь код слишком длинный):

   while(k<75){  

      domainz1.getVerticalBoundaryBegin(xz1,e1,row);
      domainz2.getVerticalBoundaryBegin(xz2,e2,row);
      domainz3.getVerticalBoundaryBegin(xz3,e3,row);
      domainz4.getVerticalBoundaryBegin(xz4,e4,row);
      domainz5.getVerticalBoundaryBegin(xz5,e5,row);
      domainz6.getVerticalBoundaryBegin(xz6,e6,row);


      domaine1.drichletFunctionalUpdateVertical(Ae1,be1,e1,ydimDom);
      domaine2.drichletFunctionalUpdateVertical(Ae2,be2,e1,1);
      domaine2.drichletFunctionalUpdateVertical(Ae2,be2,e2,ydimDom);
      domaine3.drichletFunctionalUpdateVertical(Ae3,be3,e2,1);
      domaine3.drichletFunctionalUpdateVertical(Ae3,be3,e3,ydimDom);
      domaine4.drichletFunctionalUpdateVertical(Ae4,be4,e3,1);
      domaine4.drichletFunctionalUpdateVertical(Ae4,be4,e4,ydimDom);
      domaine5.drichletFunctionalUpdateVertical(Ae5,be5,e4,1);
      domaine5.drichletFunctionalUpdateVertical(Ae5,be5,e5,ydimDom);
      domaine6.drichletFunctionalUpdateVertical(Ae6,be6,e5,1);
      domaine6.drichletFunctionalUpdateVertical(Ae6,be6,e6,ydimDom);
      domaine7.drichletFunctionalUpdateVertical(Ae7,be7,e6,1);

      gmressolver2d(Ae1,xe1,be1,KrylovDim,xdim,ydimDom,COP,twoDimStencil,0,1);
      gmressolver2d(Ae2,xe2,be2,KrylovDim,xdim,ydimDom,COP,twoDimStencil,0,1);
      gmressolver2d(Ae3,xe3,be3,KrylovDim,xdim,ydimDom,COP,twoDimStencil,0,1);
      gmressolver2d(Ae4,xe4,be4,KrylovDim,xdim,ydimDom,COP,twoDimStencil,0,1);
      gmressolver2d(Ae5,xe5,be5,KrylovDim,xdim,ydimDom,COP,twoDimStencil,0,1);
      gmressolver2d(Ae6,xe6,be6,KrylovDim,xdim,ydimDom,COP,twoDimStencil,0,1);
      gmressolver2d(Ae7,xe7,be7,KrylovDim,xdim,ydimDom,COP,twoDimStencil,0,1);

      //*******************************************************************
      domaine1.getVerticalBoundaryBegin(xe1,z1,row);
      domaine2.getVerticalBoundaryBegin(xe2,z2,row);
      domaine3.getVerticalBoundaryBegin(xe3,z3,row);
      domaine4.getVerticalBoundaryBegin(xe4,z4,row);
      domaine5.getVerticalBoundaryBegin(xe5,z5,row);
      domaine6.getVerticalBoundaryBegin(xe6,z6,row);
      domaine7.getVerticalBoundaryBegin(xe7,z7,row);


      domainz1.drichletFunctionalUpdateVertical(Az1,bz1,z1,1);
      domainz1.drichletFunctionalUpdateVertical(Az1,bz1,z2,ydimDom);
      domainz2.drichletFunctionalUpdateVertical(Az2,bz2,z2,1);
      domainz2.drichletFunctionalUpdateVertical(Az2,bz2,z3,ydimDom);
      domainz3.drichletFunctionalUpdateVertical(Az3,bz3,z3,1);
      domainz3.drichletFunctionalUpdateVertical(Az3,bz3,z4,ydimDom);
      domainz4.drichletFunctionalUpdateVertical(Az4,bz4,z4,1);
      domainz4.drichletFunctionalUpdateVertical(Az4,bz4,z5,ydimDom);
      domainz5.drichletFunctionalUpdateVertical(Az5,bz5,z5,1);
      domainz5.drichletFunctionalUpdateVertical(Az5,bz5,z6,ydimDom);
      domainz6.drichletFunctionalUpdateVertical(Az6,bz6,z6,1);
      domainz6.drichletFunctionalUpdateVertical(Az6,bz6,z7,ydimDom);

      gmressolver2d(Az1,xz1,bz1,KrylovDim,xdim,ydimDom,COP,twoDimStencil,0,1);
      gmressolver2d(Az2,xz2,bz2,KrylovDim,xdim,ydimDom,COP,twoDimStencil,0,1);
      gmressolver2d(Az3,xz3,bz3,KrylovDim,xdim,ydimDom,COP,twoDimStencil,0,1);
      gmressolver2d(Az4,xz4,bz4,KrylovDim,xdim,ydimDom,COP,twoDimStencil,0,1);
      gmressolver2d(Az5,xz5,bz5,KrylovDim,xdim,ydimDom,COP,twoDimStencil,0,1);
      gmressolver2d(Az6,xz6,bz6,KrylovDim,xdim,ydimDom,COP,twoDimStencil,0,1);


      k  ;

      printf("%d iterations donen",k);
  }
  

Здесь почти все термины в скобках являются массивами.

Ae1, Ae2, Az1, Az2, ….. являются 2D-массивами 71×11

xe1,xz1,bz1,be1,e1, e2, z1, z2,……… это одномерные массивы размером (71×11).

Эти операторы класса в основном передают данные между этими массивами. это научный код, gmressolver2d решает новые проблемы на каждой итерации.

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

С наилучшими пожеланиями, Эмре.

редактировать: мои выделения массива.

 template <typename T> 
T ****AllocateDynamic4DArray( int nRows, int nCols, int nSlice, int kSlice)
{
      T ****dynamicArray;

      dynamicArray = new T***[nRows];
      for( int i = 0 ; i < nRows ; i   ){
        dynamicArray[i] = new T**[nCols];
        for ( int j=0; j<nCols;j  ){
            dynamicArray[i][j] = new T*[nSlice];
            for (int k=0; k<nSlice; k  ){
                dynamicArray[i][j][k] = new T[kSlice];
                for(int l=0;l<kSlice;l  ){
                    dynamicArray[i][j][k][l] = 0;
                }
            }
        }
      }
      return dynamicArray;
}
template <typename T>
T ***AllocateDynamic3DArray(int nRows, int nCols, int nSlice){
      T ***dynamicArray;

      dynamicArray = new T**[nRows];
      for( int i = 0 ; i < nRows ; i   ){
        dynamicArray[i] = new T*[nCols];
        for ( int j=0; j<nCols;j  ){
            dynamicArray[i][j] = new T[nSlice];
            for (int k=0; k<nSlice; k  ){
                    dynamicArray[i][j][k]= 0;
                }
            }
        }
      return dynamicArray;
}
template <typename T>
T **AllocateDynamic2DArray(int nRows, int nCols){
      T **dynamicArray;

      dynamicArray = new T*[nRows];
      for( int i = 0 ; i < nRows ; i   ){
        dynamicArray[i] = new T[nCols];
        for ( int j=0; j<nCols;j  ){
                dynamicArray[i][j]= 0;
            }
        }
      return dynamicArray;
}
template <typename T>
T *AllocateDynamicVector(int nRows){
      T *dynamicArray;

      dynamicArray = new T[nRows];
      for( int i = 0 ; i < nRows ; i   ){
            dynamicArray[i]= 0;
        }
      return dynamicArray;
}
  

Комментарии:

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

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

3. Сколько оперативной памяти в вашей системе? Обычно это исключение выдается new , когда у вас заканчивается память. Также для каждого цикла обычно выделяется сколько памяти? При повторении цикла вам нужно, чтобы каждый сгенерированный элемент в куче оставался в памяти с предыдущей итерации цикла?

4. @Jason: У меня 4 ГБ оперативной памяти. Я пытался увеличить размер кучи, но мое распределение оперативной памяти в любом случае увеличивается до 100%. Нет, мне не нужен каждый сгенерированный элемент, я могу удалить e1 ….e6 amp; z1 ….z6, если необходимо. может быть, мне следует выделить и удалить их в цикле while? помогло бы это?

5. @Oswald @honk: Функции просто принимают динамические массивы и передают информацию между ними. В этих функциях не инициализируется новый массив.

Ответ №1:

Запустите программу в вашем отладчике и настройте отладчик так, чтобы он прерывался при возникновении исключения. Как только программа остановлена (из-за исключения), используйте функцию стека вызовов вашего отладчика, чтобы увидеть, в каком контексте генерируется ваше исключение.

Я хотел бы дать вам более подробные инструкции, но вы не указали, какую платформу / компилятор вы используете.


В этом руководстве описывается, как настроить Visual Studio на прерывание работы при любом исключении.

В этом руководстве описывается, как использовать стек вызовов.

Комментарии:

1. спасибо, Эмиль, теперь я знаю, в чем проблема. Я все еще немного сбит с толку. Это другой вопрос — но разве вы не можете удалить многомерный массив «A» как «delete[] A», или вам нужно установить цикл для этого?

2. @Emre: Это зависит. Это массив массивов? Или это плоский одномерный массив, где вы вычисляете одномерный индекс из пары двумерных индексов? Просто покажите нам, как вы распределяете эти 2D-массивы, и мы узнаем, какие.

3. @Emre: Да, вы должны удалить[] все вложенные массивы в цикле.

4. Я всего лишь писал «удалить [] A», независимо от того, является ли это массивом 4D или 1D .. спасибо, Эмиль.

Ответ №2:

Использовать UMDH.EXE чтобы сделать снимки использования кучи приложения перед последовательными циклами, затем сравните два снимка. При правильной настройке будут видны стеки вызовов всех промежуточных действий.

Ответ №3:

При удалении массивов тем способом, которым вы их выделяете, один вызов delete [] array_name не будет работать, потому что каждый индекс в измерении массива является недавно выделенным «подмассивом» указателей. Итак, вам придется перебирать каждую строку / столбцы / фрагмент / и т.д. Массива и вызывать delete [] массив указателей, которые составляют индексы массива. Например, чтобы освободить один из ваших 3D-массивов, вам нужно будет сделать что-то вроде следующего:

 for (int i=0; i < column_size; i  )
{
    for (int j=0; j < slice_size; j  )
    {
        delete [] array_name[i][j];
    }

    delete [] array_name[i];
}

delete [] array_name;