C++ MFC程序中的堆损坏

C++ MFC程序中的堆损坏,c++,mfc,heap-corruption,C++,Mfc,Heap Corruption,我在程序中遇到堆损坏问题。在程序中,我读取一块数据并对其执行FFT和IFFT。我做了两个图像,主人和奴隶。完全相同的代码对于主文件很好,但是当我试图删除从属缓冲区时,显示了从属文件的堆损坏 fcomplex定义为: typedef struct {float real, imag;}fcomplex; 随附代码相关部分的片段: 完整代码: 如果不调用从属映像的fft和ifft函数,则不会发生错误。(不过对主人来说一切都很好) 为了调试错误,我安装了应用程序验证程序,但无法解码日志文件。此处:(

我在程序中遇到堆损坏问题。在程序中,我读取一块数据并对其执行FFT和IFFT。我做了两个图像,主人和奴隶。完全相同的代码对于主文件很好,但是当我试图删除从属缓冲区时,显示了从属文件的堆损坏

fcomplex定义为:

typedef struct {float real, imag;}fcomplex;
随附代码相关部分的片段: 完整代码:

如果不调用从属映像的fft和ifft函数,则不会发生错误。(不过对主人来说一切都很好)

为了调试错误,我安装了应用程序验证程序,但无法解码日志文件。此处:(粘贴XML文件副本)

visual studio给出的错误是: 检测到堆损坏:在0x062C0040的正常块(#194456)之后

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%有效。为什么奴隶会崩溃

有人能给我一个解决方案或者一个关于如何使用应用程序验证程序的教程吗

谢谢, 肖纳克

编辑:使用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;
}

首先,了解堆损坏错误告诉您的是什么很重要。在Visual Studio中运行调试生成时,它使用具有调试堆的运行时库的调试版本。每当您使用
new
分配一些内存时,内存两侧都会有一些额外的保护字节。当您
delete
it时,调试堆将检查这些保护字节是否完整,如果不完整,则会发出此警告

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

XXXXXX - guard bytes
slave_bfr
XYXYXY - these are the guard bytes that are probably being corrupted
slave_cols
XXXXXX
您在
从属列上执行操作
Pcoarse.cfft1d\(
),但删除
从属列时会出现堆损坏错误。这表明
cfft1d_u()
slave_ucols
启动之前覆盖内存,从而损坏
slave_ubfr
的保护字节

因此,我将在您的代码中查找
cfft1d_u2;()
可能具有负数组索引的位置,因为这可能会导致
slave_2;bfr
中的内存被踩踏

此外,还可以使用一些有用的提示来检查,这些提示说明如何充分利用调试堆,特别是如何启用更密集的内存检查。

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

你可以这么做

delete [] cf;
cf = NULL;
您有两行代码如下所示:

four1(cf-1,nn,isign);
我认为这是在数组开始之前访问内存


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

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

如何定义
init_1Dcmplx
?它是否使用
new…[]
分配结构?@nneonno是。请参阅EDIT2Post的cfft1d\的代码,它是相关的部分。@lyritat好,del\ u float不太正确。它删除了数组,但并没有像看上去那样将指针设置回NULL。这是因为它是在指针的副本上操作的。但是指针在之后没有被使用,所以我不认为这是最终的原因。我将研究它的行为。但是,对于主文件,该函数在第一次调用时运行良好。非常感谢您的持续帮助。不过,我在索引方面错了,我已经删除了该部分。我想看看我能对该函数做些什么更改。但我看不出有什么问题:该函数将cf初始化为2*n值[比如32]。“i”将持续到30,因此索引31将有效。n的约束条件是它必须是2的幂,因此代码在IMO中是有效的。编辑:对不起!没有看到你的更新,抱歉!我是在你发布编辑时输入的!我会调查新问题的。F11'ing:)更改太多four1(cf、nn、isign)会产生新的堆错误。但我认为这个解决方案是正确的,至少为我指明了正确的方向。我可能还不能调试fft代码。我能以某种方式解决这个问题吗?谢谢你提供的信息。我试图通过您提供的链接和本页其他人的建议对此进行调试,即使我只是简单地调用从属序列,这也是我个人希望的,因为我对指针/原始数组不太熟悉,但所有旧代码都使用这种结构,包括我需要调用的函数,如fft等。也许我可以尝试分配一个更大的块,或者我的分配大小是错误的,因为代码在主程序中运行得非常完美。如果我将slave_bfr=Pcoarse.init_1Dcmplx(size_cols)替换为slave_bfr=Pcoarse.init_1Dcmplx(size_cols+1),它不会给我任何错误。但是在delete语句之后,我还有一个30mb的块。
four1(cf-1,nn,isign);