【问题标题】:exception: std::bad_alloc at memory location in a loop异常:循环中内存位置的 std::bad_alloc
【发布时间】:2011-08-14 22:21:44
【问题描述】:

我有一个内存分配问题。但是不知道问题出在哪里

在第 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 done\n",k);
  }

这里几乎所有括号中的术语都是数组。

Ae1,Ae2,Az1,Az2,..... 是 71x11 的二维数组

xe1,xz1,bz1,be1,e1,e2,z1,z2,......... 是大小为 (71x11) 的一维数组。

这些类操作符基本上是在这些数组之间传输数据。这是一个科学代码,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;
}

【问题讨论】:

  • 循环中没有分配内存。问题在于循环期间执行的函数之一。请给出这些函数的定义。
  • 这很难回答。您的问题基本上是您的内存不足,但我们不知道内存分配在哪里,因为您的任何函数都可能这样做。你能举个例子吗?
  • 你的系统有多少内存?通常,当您的内存不足时,new 会抛出该异常。同样对于每个循环,通常分配多少内存?重复循环时,是否需要堆上的每个生成项都保留在上一次循环迭代的内存中?
  • @Jason:我有 4GB 的 RAM。我试图增加堆大小,但无论如何我的 ram 分配上升到 100%。不,我不需要每个生成的项目,如有必要,我可以删除 e1....e6 和 z1....z6。也许我应该在while循环中分配和删除它们?会有帮助吗?
  • @Oswald @honk:这些函数只是采用动态数组并在其间传输信息。在这些函数中没有初始化新数组。

标签: c++ exception memory-leaks memory-management


【解决方案1】:

使用UMDH.EXE 在连续循环之前拍摄应用程序堆使用情况的快照,然后比较两个快照。如果设置正确,将可以看到过渡期间所有分配的调用堆栈。

【讨论】:

    【解决方案2】:

    在调试器中运行程序,并设置调试器,使其在抛出异常时中断。一旦程序停止(由于异常),请使用调试器的调用堆栈功能查看在哪个上下文中引发了异常。

    我想给你更详细的说明,但你没有指定你正在使用什么平台/编译器。


    how-to 描述了如何设置 Visual Studio 以在任何异常时中断。

    这个how-to 描述了如何使用调用堆栈。

    【讨论】:

    • 谢谢emile,现在我知道问题出在哪里了。我还是有点困惑。这是另一个问题——但你不能将多维数组“A”删除为“delete[] A”,还是必须为此设置一个循环?
    • @Emre:这取决于。它是一个数组数组吗?或者它是一个扁平的一维数组,您可以在其中从一对二维索引中计算一维索引?只需向我们展示您是如何分配这些二维数组的,我们就会知道是哪一个。
    • @Emre:是的,你必须在一个循环中删除[]所有嵌套数组。
    • 我只写了“delete[] A”,不管是 4D 还是 1D 数组。谢谢 emile。
    【解决方案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;
    

    【讨论】:

      猜你喜欢
      • 2013-12-20
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-03
      • 1970-01-01
      • 2020-04-09
      相关资源
      最近更新 更多