views:

317

answers:

3

I have stumbled accross a strange problem in which I cannot understand. I am not an expert at C/C++ so bear with me. I have an NPC class, which derives from a Player class, which derives from a Sprite class. The sprite class contains a setupAnimation function, which allocates an array of floats containing coordinates on the texture, each element of the array refers to a frame of animation. This is all good and works fine.

However, a problem occurs when I add an array of pointers to the NPC class. These pointers are of an Item class type. When I add this array, it works fine if the array is small (10 was the size I tested), but will crash when allocating the array of floats for texture coordinates mentioned earlier if the size is a bit larger (100 was the size I tested).

Here are some code fragments showing the material I mentioned above:

The Item class array of pointers:

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

The texture coordinates and their allocation counterparts:

    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];

This fragment of code is the basis of every class that derives from the Sprite class. What I can't understand is why an extra 90 pointers causes a problem during the float allocation. Just a bit of software information to go with this

OS: Windows Vista 32-bit, Compiler: Visual C++ 9.0, Program runtime memory: ~17,600k, System memory: ~2GB

With this in mind, I can't see it being memory running dry, and I can't tie in how an array of pointers causes the allocation to fail. As mentioned, the allocation works fine in all other classes derived from Sprite (as well as Sprite itself), but once this array of pointers is added the the NPC class, the NPC will no longer allocate this texture data float array without crashing.

+3  A: 

The symptoms you describe are typical of a corrupted memory allocation system. The fact that the error occurs where you say it does probably is not significant - the real error is almost certainly elsewhere.

There are lots of ways of reducing the chances of this happening, but the major one is to write code in C++, not C with a bit of C++ syntax. Use collections like std::vector that perform their own memory management rather than attempting to do it yourself.

anon
+5  A: 

Somewhere else in your program, you probably have some sort of memory error (wrote past the end of an array, wrote to freed memory, etc.). When this happens, it is possible that you can overwrite structures used by the memory allocation system, causing it to crash on the next allocation. It might help to run your program with a tool like Valgrind to find where the error is. EDIT: I just realized that you're using Windows and Valgrind only works on Linux. If your code is portable enough, it would be relatively easy to try Linux and Valgrind. If you can't do that, see Is there a good Valgrind substitute for windows? on SO. (Unfortunately, it looks like most of them are commercial, not free and open source like Valgrind.)

The best way to avoid this is to use C++ collections such as std::vector or std::list rather than arrays. If you use these collections, make sure you keep the copying to a minimum (e.g. use const references as parameters rather than copies of the original object if you don't modify it, etc.), or you will get very bad performance (and it looks like you're doing a game, so this is important).

Zifre
Thank you for the fast reply. I const reference as much as possible already. I will use vector more often, but I have always frowned upon libraries that do what I can do myself, since they are setup in a way I don't like. It is the basis of a bad programmer I know, and I will most likely grow out of it.Thanks again anyway, much appreciated (As well as thanks to Neil above).
I'd start that change now. Re-inventing the wheel is terrible. What about them isn't setup how you like?
GMan
A: 

As already said, this very much looks like memory corruption.

To narrow down where the real error is located, run in debug mode and try to increase the frequency with which the CRT checks the heap for corruption.

The following code taken from the MSDN shows how to let the CRT check every 16 heap operations instead of every 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);
}

For more information, see _CrtSetDbgFlag in MSDN

Jan