内存分配崩溃

时间:2009-07-27 13:29:57

标签: c++ memory crash pointers new-operator

我偶然发现了一个我无法理解的奇怪问题。我不是C / C ++的专家,所以请耐心等待。我有一个NPC类,它派生自一个Player类,它派生自Sprite类。 sprite类包含一个setupAnimation函数,该函数分配一个包含纹理坐标的浮点数组,数组的每个元素都指向一帧动画。这一切都很好,工作正常。

但是,当我向NPC类添加一个指针数组时会出现问题。这些指针属于Item类类型。当我添加这个数组时,如果数组很小(10是我测试的大小),它可以正常工作,但如果大小有点大(100是我的大小,则为前面提到的纹理坐标分配浮点数组时会崩溃)测试)。

以下是一些代码片段,显示了我上面提到的材料:

Item类的指针数组:

    engItem* itsLoot[100]; // With 100 here, the crash occurs as shown below

纹理坐标及其分配对应物:

    GLfloat* itsTextureXData;
    GLfloat* itsTextureYData;

    ...

    animationFile >> frameCount; // Tested, the value is correct

    engDeallocate(getTextureXData(), true); // Works fine
    itsTextureXData = new GLfloat[frameCount]; // This is where the crash occurs

    engDeallocate(getTextureYData(), true);
    itsTextureYData = new GLfloat[frameCount];

这段代码是派生自Sprite类的每个类的基础。我无法理解的是为什么在浮动分配期间额外的90个指针会导致问题。只需要一些与此相关的软件信息

操作系统:Windows Vista 32位,编译器:Visual C ++ 9.0,程序运行时内存:~17,600k,系统内存:~2GB

考虑到这一点,我无法看到内存正在运行干涸,我无法确定指针数组如何导致分配失败。如上所述,分配在从Sprite派生的所有其他类(以及Sprite本身)中都能正常工作,但是一旦这个指针数组被添加到NPC类中,NPC将不再分配这个纹理数据float数组而不会崩溃。 / p>

3 个答案:

答案 0 :(得分:6)

程序中的其他地方,您可能会遇到某种内存错误(写入数组末尾,写入释放内存等)。发生这种情况时,您可能会覆盖内存分配系统使用的结构,导致它在下一次分配时崩溃。使用Valgrind之类的工具运行程序可能有助于查找错误的位置。 编辑:我刚刚意识到你正在使用Windows而Valgrind只适用于Linux。如果您的代码足够便携,那么尝试Linux和Valgrind会相对容易。如果您不能这样做,请参阅SO上的Is there a good Valgrind substitute for windows?。 (不幸的是,看起来大多数都是商业性的,而不像Valgrind那样免费和开源。)

避免这种情况的最佳方法是使用C ++集合,例如std::vectorstd::list而不是数组。如果您使用这些集合,请确保将复制保持在最低限度(例如,使用const引用作为参数而不是原始对象的副本(如果您不修改它等),或者您将获得非常好的糟糕的表现(看起来你正在做游戏,所以这很重要)。

答案 1 :(得分:3)

您描述的症状是典型的内存分配系统损坏。错误发生在你说它的地方的事实可能并不重要 - 真正的错误几乎可以肯定在其他地方。

有很多方法可以减少这种情况发生的可能性,但主要方法却是如此 是用C ++编写代码,而不是用C ++语法编写C代码。使用像std :: vector这样的集合来执行自己的内存管理而不是自己尝试。

答案 2 :(得分:0)

如前所述,这非常像内存损坏。

要缩小实际错误所在的位置,请在调试模式下运行并尝试增加CRT检查堆损坏的频率。

以下从MSDN获取的代码显示了如何让CRT检查每16个堆操作而不是每1024个操作:

#include <crtdbg.h>
int main( )
{
int tmp;

// Get the current bits
tmp = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);

// Clear the upper 16 bits and OR in the desired freqency
tmp = (tmp & 0x0000FFFF) | _CRTDBG_CHECK_EVERY_16_DF;

// Set the new bits
_CrtSetDbgFlag(tmp);
}

有关详细信息,请参阅_CrtSetDbgFlag in MSDN