Reputation: 11
[Fore note: I have read the existing threads in StackOverflow. None seemed to be on my question]
I am looking into the Quake 2 MD2 format. I seem to be getting a bad allocation after new'ing a pointer-array. However, if I do some horrible pointer manipulation, everything is fine. I guess the question is, why am I getting such an exception?
The first "MD2Model::Load" works. The one I posted after it gets the exception.
Basic structures :
struct MD2Header
{
int nIdentifier;
int nVersion;
int nSkinWidth;
int nSkinHeight;
int nFrameSize;
int nNumSkins;
int nNumVertices;
int nNumUV;
int nNumTriangles;
int nNumCmds;
int nNumFrames;
int nOffsetSkins;
int nOffsetUV;
int nOffSetTriangles;
int nOffsetFrames;
int nOffsetCmds;
int nOffsetEnd;
};
struct MD2Skin
{
char szName[64];
};
struct MD2TexCoord
{
short t;
short u;
};
struct MD2Triangle
{
short nVertex[3];
short tu[3];
};
struct MD2Vertex
{
float fVertex[3];
float fNormal[3];
};
struct MD2Frame
{
char szName[16];
MD2Vertex* pVerts;
};
And now, the function that reads the .md2 file:
bool MD2Model::Load( const char* pszName )
{
FILE* pFile = NULL;
fopen_s( &pFile, pszName, "rb" );
if( !pFile )
return false;
/* Read Header */
fread( &m_Header, sizeof(MD2Header), 1, pFile );
/* Allocate Pointers */
m_pSkins = new MD2Skin[m_Header.nNumSkins];
m_pTexCoords = new MD2TexCoord[m_Header.nNumUV];
m_pTriangles = new MD2Triangle[m_Header.nNumTriangles];
m_pFrames = new MD2Frame[m_Header.nNumFrames];
/* Read Skins */
fseek( pFile, m_Header.nOffsetSkins, SEEK_SET );
fread( m_pSkins, sizeof(MD2Skin), m_Header.nNumSkins, pFile );
/* Read Texture Coords */
fseek( pFile, m_Header.nOffsetUV, SEEK_SET );
fread( m_pTexCoords, sizeof(MD2TexCoord), m_Header.nNumUV, pFile );
/* Read Faces */
fseek( pFile, m_Header.nOffSetTriangles, SEEK_SET );
fread( m_pTriangles, sizeof(MD2Triangle), m_Header.nNumTriangles, pFile );
/* Read Animations */
struct stMD2Vertex
{
unsigned char nVertex[3];
unsigned char nLightNormalIndex;
};
struct stMD2Frame
{
float fScale[3];
float fTranslate[3];
char szName[16];
stMD2Vertex verts[1];
};
unsigned char pBuffer[30000];
stMD2Frame* pTmp = (stMD2Frame*) pBuffer;
fseek( pFile, m_Header.nOffsetFrames, SEEK_SET );
for( int i = 0; i < m_Header.nNumFrames; i++ )
{
fread( pTmp, 1, m_Header.nFrameSize, pFile );
m_pFrames[i].pVerts = new MD2Vertex[m_Header.nNumVertices];
strcpy_s( m_pFrames[i].szName, pTmp->szName );
for( int j = 0; j < m_Header.nNumVertices; j++ )
{
m_pFrames[i].pVerts[j].fVertex[0] = pTmp->verts[j].nVertex[0] *
pTmp->fScale[0] + pTmp->fTranslate[0];
m_pFrames[i].pVerts[j].fVertex[2] = -1 * (pTmp->verts[j].nVertex[1] *
pTmp->fScale[1] + pTmp->fTranslate[1]);
m_pFrames[i].pVerts[j].fVertex[1] = pTmp->verts[j].nVertex[2] *
pTmp->fScale[2] + pTmp->fTranslate[2];
}
}
return true;
}
Variables dumped during debugging:
nNumSkins 1 int
nNumVertices 583 int
nNumUV 582 int
nNumTriangles 422 int
nNumFrames 1 int
(I ended up removing my D3DXVECTOR3 structures to see, so it's kinda fugly..)
Alright. So, inside the 'for' loop, is where it blows up. If I were to do it like this:
// unsigned char pBuffer[30000];
// stMD2Frame* pTmp = (stMD2Frame*) pBuffer;
fseek( pFile, m_Header.nOffsetFrames, SEEK_SET );
for( int i = 0; i < m_Header.nNumFrames; i++ )
{
stMD2Frame* pTmp = new stMD2Frame();
fread( pTmp, 1, m_Header.nFrameSize, pFile );
m_pFrames[i].pVerts = new MD2Vertex[m_Header.nNumVertices];
strcpy_s( m_pFrames[0].szName, pTmp->szName );
I get the bad_alloc exception during allocating the "m_pFrames[i].pVerts" statement. Sometimes, I don't get it, but I do get the exception when I try to new my D3D class (I'm assuming I'll get it no matter what I new afterwards). My MEM usage is extremely low, so could it be heap corruption?
I actually had to end up doing this during creating my VertexBuffer during animations as well.
Should I end up using vectors? I know they allocate more than needed, but it seems like the (most obvious)[best] way.
Upvotes: 1
Views: 1827
Reputation: 33509
I would check the line:
strcpy_s( m_pFrames[0].szName, pTmp->szName );
If the string loaded from the file is not null-terminated then this copy could end up overwriting your stack space and causing corruption.
EDIT
Looking again, I think the problem is that you define stMD2Frame as
struct stMD2Frame
{
float fScale[3];
float fTranslate[3];
char szName[16];
stMD2Vertex verts[1];
};
but this only has space for one vertex.
When you read in the frame as
fread( pTmp, 1, m_Header.nFrameSize, pFile );
you will corrupt your memory.
I suggest a check that
sizeof(stMD2Frame)>=m_Header.nFrameSize
before reading the data.
Upvotes: 2