在MFC计划中堆积腐败

时间:2012-08-28 07:34:00

标签: c++ mfc heap-corruption

我遇到程序中的堆损坏问题。在程序中,我正在读取数据块并对其执行FFT和IFFT。我正在为2个图像,主人和奴隶做这件事。 EXACT相同的代码适用于主服务器,但在我尝试删除从属缓冲区时显示从属文件的堆损坏。

fcomplex定义为:

typedef struct {float real, imag;}fcomplex;

附上代码相关部分的片段: 完整代码:http://sharetext.org/7xXe

如果我没有为从属图像调用fft和ifft函数,则不会发生错误。 (虽然对于大师来说一切正常)

调试错误我安装了应用程序验证程序,但我无法解码日志文件。它在这里:http://sharetext.org/Y2ji(粘贴XML文件副本)

视觉工作室给出的错误是: 检测到堆损坏:在正常块(#194456)之后的0x062C0040

CCoarseFun::fcomplex * slave_bfr;
CCoarseFun::fcomplex * slave_col;


slave_bfr = Pcoarse.init_1Dcmplx(SIZE*s_cols); 
slave_col = Pcoarse.init_1Dcmplx(SIZE);

Pcoarse.cfft1d_(&SIZE,slave_col,&FFTdir); // This function causes a problem
Pcoarse.complex_mult_col(filter, slave_col, SIZE, slave_col)
Pcoarse.cfft1d_(&SIZE,slave_col,&FFTdir); // As does this one

// delete memory related to slave
delete [] slave_bfr;    // Heap corruption here
delete [] slave_col;

令我感到困惑的是,代码非常简单,仅对主文件有效100%。为什么它会为奴隶崩溃?

有人可以指导我一个解决方案,或者也可以参考如何使用应用程序验证程序的教程吗?

谢谢, Shaunak

编辑:使用Win7 x64 - VS2010

编辑2:init_1Dcmplx的定义

CCoarseFun::fcomplex* CCoarseFun::init_1Dcmplx(int n)
{
  fcomplex *a;
  a=new fcomplex[n];
  for(int i=0;i<n;i++)
  {
    a[i].real=float(0.0);
    a[i].imag=float(0.0);
  }
  return a;
}

EDIT3:cfft1D_的编号:http://sharetext.org/hzIg

EDIT4:mem.delfloat()的代码

void CMemAlloc::del_float(float *a)
{
  if (a!=NULL)
  {
    delete[] a;
    a=NULL;
  }
  else
  {
    return;
  }
}

3 个答案:

答案 0 :(得分:1)

mem_float()函数不正确。看起来它在删除后将指针设置为NULL,但它只处理指针的副本,因此调用者的副本仍然指向已删除的内存块。

你可以做到

delete [] cf;
cf = NULL;

你有几行看起来像这样:

four1(cf-1,nn,isign);

我认为这是在数组开始之前访问内存。

除此之外,four1()内的索引非常复杂 - 您必须使用调试器逐步检查边缘情况。

答案 1 :(得分:0)

首先,了解堆损坏错误告诉您的内容非常重要。在Visual Studio中运行Debug构建时,它使用具有调试堆的运行时库的Debug版本。每当你用new分配一些内存时,它的两侧都有一些额外的保护字节。当你delete时,调试堆会检查那些保护字节是否完整,如果没有,则会发出此警告。

假设Pcoarse.init_1Dcmplx()在堆上分配内存,那么对它的两次调用很可能会一个接一个地分配内存:

XXXXXX - guard bytes
slave_bfr
XYXYXY - these are the guard bytes that are probably being corrupted
slave_cols
XXXXXX

您在Pcoarse.cfft1d_()上执行操作slave_cols,但在删除slave_bfr时会出现堆损坏错误。这表明cfft1d_()slave_cols开始之前覆盖了内存,因此它会破坏slave_bfr的保护字节。

因此,我会查看cfft1d_()的代码,查找可能包含负数组索引的地方,因为这可能导致slave_bfr中的内存被踩踏。

还要检查一些SO answers,其中包含有关如何充分利用调试堆的有用提示,特别是this one,了解如何启用更密集的内存检查。

答案 2 :(得分:0)

“检测到堆损坏:在正常块(#194456)之后在0x062C0040”说你分配了一个块,得到块#194456,地址为0x062C0040,你写的内存字节比你分配的多。所以你有一个经典的缓冲区溢出。您应该考虑用STL容器替换指针。在你的情况下,我更喜欢在分配有std::vector的原始浮点数组上使用new float[]。 STL容器可以帮助您在错误访问时立即检测超出边界的写入,而不仅仅是在删除内存块之后。