我遇到程序中的堆损坏问题。在程序中,我正在读取数据块并对其执行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;
}
}
答案 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容器可以帮助您在错误访问时立即检测超出边界的写入,而不仅仅是在删除内存块之后。