2014-10-08 148 views
0

我有一个字节数组,如下所示:C++堆损坏DETECTED - CRT

BYTE* m_pImage; 
m_pImage = new BYTE[m_someLength]; 

而在我的节目数据的各个阶段将被复制到该阵列像这样:

BYTE* pDestinationBuffer = m_pImage + m_imageOffset; 
memcpy(pDestinationBuffer, (BYTE*)data, dataLength); 

但是,当我去删除我的缓冲区像这样:

delete[] m_pImage; 

我收到 HEAP CORRUPTI检测到 - CRT检测到应用程序在堆缓冲区结束后写入内存

现在我尝试了一个简单的程序来尝试并复制该错误,以帮助我调查发生了什么。我从下面看到,如果我创建了一个大小为5的数组,但是在它的末尾写下并尝试删除它,我会得到完全相同的错误。

int* myArray = new int[5]; 
myArray[0] = 0; 
myArray[1] = 1; 
myArray[2] = 2; 
myArray[3] = 3; 
myArray[4] = 4; 
myArray[5] = 5; // writing beyond array bounds 

delete[] myArray; 

现在我的问题是我怎么可能调试或找出什么是覆盖我原来的缓冲区。我知道某些东西会覆盖缓冲区的末尾,所以有没有办法让visual studio帮助我轻松地进行调试。

上面那个复制到数据缓冲区的代码在删除之前会被调用几次,所以很难保持m_pImage内容和复制到它的数据的跟踪。 (其大约2M价值的数据)

+1

你可以使用像valgrind这样的工具来找到错误。你也可以检查'm_imageOffset + dataLength <= m_someLength'。从根本上说,你付出的代价是使用原始数组而不是'std :: vector'。 – 2014-10-08 19:25:05

+3

'm_pImage + m_imageOffset + dataLength'将会是'> m_someLength' – 2014-10-08 19:25:27

+0

在visual studio中有内存断点,你可以尝试在缓冲区的最后设置一个 – PeterT 2014-10-08 19:25:34

回答

2

现在我的问题是我怎么可能调试或找出什么是覆盖我原来的缓冲区。

我建议尽可能使用assert()声明。在这种情况下应该是:

BYTE* pDestinationBuffer = m_pImage + m_imageOffset; 
assert(dataLength + m_imageOffset <= m_someLength); 
memcpy(pDestinationBuffer, (BYTE*)data, dataLength); 

然后编译到调试模式并运行。这种方法的好处 - 在释放模式下,不会评估任何断言。

+0

当然,它会更清洁地使用'std :: vector'并避免重新发明轮子 – 2014-10-08 19:39:23

+0

@DavidHeffernan其实我怀疑'std :: vector'会有助于这种情况,'std :: vector'中的数据会去超出界限完全一样的方式,如果逻辑错误不会被修复 – Slava 2014-10-08 19:42:12

+0

调试MSVC运行时有界限检查'std :: vector',除非我误认为 – 2014-10-08 19:43:59

0

堆腐败是一个难以发现的错误。大多数情况下,当报告错误时,内存已经被之前执行的一些上游代码破坏了。如果您决定使用应用程序验证程序(并且您应该),我还建议您尝试GFLags and PageHeap。他们是一些额外的工具,允许您设置注册表标志来调试这些类型的问题。