2

我偶然发现了一个我无法理解的奇怪问题。我不是 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 将不再分配此纹理数据浮点数组而不会崩溃。

4

3 回答 3

6

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

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

于 2009-07-27T13:45:36.067 回答
3

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

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

于 2009-07-27T13:33:20.543 回答
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);
}

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

于 2009-07-27T15:43:41.767 回答