I return with another perplexing issue that I just can't figure out, a generic and unhelpful"std::bad_alloc at memory location" error. Before I get to the code, some background...
Having finished my uber-awesome 2D engine (thanks entirely to you guys) I decided it was time to break open the can of worms that is the third dimension! twiddled VC2008's dials and threw in some OpenGL (DirectX got old really fast).
So far every things gone swimmingly, I've got sprites, partials, 3d models, even a basic environment! It's not even close to optimised but it's just for learning and bragging rights really... Then down comes the hammer of my error.

What I'm basically doing is adding a function to load wavefront OBJ models, after some annoying glitches I got that working fine, happyfaces all around. However the problem seems to occur not when I generate one of these meshes, but rather when I try to use them in one of my more complex classes.

In short I have a mesh class that hold pointers to memory containing the lists of vertex's UV coords.. just generic data really.
This mesh class, is in-turn pointed to by a 'model' class, this is so that many models can use the same mesh without having to load it several times (and using up memory like magnetic tape in a 1960's render farm).
So far all this works (or at least seems to) work fine. function loads data into pointers, these are passed to the mesh that holds the pointers, the mesh (now full of data) has it's pointer passed to the 'model' that stores that and other data (for physics simulations etc), the problem arises when trying to allocate memory for the 'compiled' mesh class, this object contains a pointer to the model, reads the data from the model and produces a 'compiled' model (basically just optimised and stored on the GPU). This in turn pointed to by a model class containing render functions.

I can't post all my code (due to the sheer quanta of it would most likely take up half the forum) So I'll include any parts I consider relivent and if you need anything else I'll be happy to oblige.

Base data storage:

typedef struct
{
	public:
    float X,Y,Z,U,V;
} PJBStdVertex;

typedef struct
{
	public:
    PJBStdVertex Vertex[3];
} PJBStdTriangle;


//Mesh Loading function (OBJ model file reader)

PJBStdMesh* PJBLoadObjMesh(char* MeshFilePath)
{
    FILE* TheMeshFile;
    TheMeshFile = fopen(MeshFilePath, "rt");

    int numtriangles;           // Number Of Triangles In total
    char oneline[255];           // String To Store Data In
	char readString[255];
    PJBStdMesh* Mesh;
    vector<PJBStdTriangle> TriangleBuffer;
	vector<PJBVec3Df> Verts;
	vector<PJBVec2Df> Uvs;
    if(TheMeshFile)
    {
		readstr(TheMeshFile,oneline);         // Get Single Line Of Data
		bool Done=false;
		while(!feof(TheMeshFile))
		{
			readstr(TheMeshFile,oneline);         // Get Single Line Of Data
			sscanf(oneline, "%255s",&readString);
			if(!strcmp(readString,"v"))
			{
				float Val1,Val2,Val3;
				sscanf(oneline, "%*s %f %f %f\n", &Val1,&Val2,&Val3);
				PJBVec3Df VertBuffer(Val1,Val2,Val3);
				Verts.push_back(VertBuffer);
			}
			else if(!strcmp(readString,"vt"))
			{
				float Val1,Val2;
				sscanf(oneline, "%*s %f %f\n", &Val1,&Val2);
				PJBVec2Df UVBuffer(Val1,Val2);
				Uvs.push_back(UVBuffer);
			}
			else if(!strcmp(readString,"f"))
			{
				int Val1,Val2,Val3,Val4,Val5,Val6;
				sscanf(oneline, "%*s %i/%i %i/%i %i/%i \n", &Val1,&Val2,&Val3,&Val4,&Val5,&Val6);
				PJBStdTriangle TriBuffer;
				for(int VertLoop=0; VertLoop < 3; VertLoop++)
				{
					if(Val1<=Verts.size() && Val1>=1)//error checking, saves your arse!
					{
					TriBuffer.Vertex[VertLoop].X=Verts[Val1-1].x;
					TriBuffer.Vertex[VertLoop].Y=Verts[Val1-1].y;
					TriBuffer.Vertex[VertLoop].Z=Verts[Val1-1].z;
					}
					else 
					{
						break;
					}
					if(Val2<=Uvs.size() && Val2>=1)//error checking, saves your arse!
					{
					TriBuffer.Vertex[VertLoop].U=Uvs[Val2-1].x;
					TriBuffer.Vertex[VertLoop].V=Uvs[Val2-1].y;
					}
					else
					{
						break;
					}
				}
				TriangleBuffer.push_back(TriBuffer);
			}
		}
        fclose(TheMeshFile);
		numtriangles=TriangleBuffer.size()-1;
		Mesh = new PJBStdMesh;
		Mesh->NumTri=numtriangles;
		PJBStdTriangle* TriBuff;
		TriBuff = new PJBStdTriangle[numtriangles];
		for(int i=0;i<TriangleBuffer.size();i++)
		{
			for(int VertLoop=0; VertLoop < 3; VertLoop++)
			{
				TriBuff[i].Vertex[VertLoop].X=TriangleBuffer[i].Vertex[VertLoop].X;
				TriBuff[i].Vertex[VertLoop].Y=TriangleBuffer[i].Vertex[VertLoop].Y;
				TriBuff[i].Vertex[VertLoop].Z=TriangleBuffer[i].Vertex[VertLoop].Z;
				TriBuff[i].Vertex[VertLoop].U=TriangleBuffer[i].Vertex[VertLoop].U;
				TriBuff[i].Vertex[VertLoop].V=TriangleBuffer[i].Vertex[VertLoop].V;
			}
		}
		Mesh->Polygons = TriBuff;
    }
    else
    {
        fclose(TheMeshFile);
        return NULL;
    }
    return Mesh;
}


//Initial call from main engine

	ModelTest = new PJBGLModel3D(ATexture,"ash.obj",Location,Velocity,Rotation); 

//High level model constructor:

PJBGLModel3D::PJBGLModel3D(PJBGLTexture* texture, char* MeshPath, PJBVec3Df Pos, PJBVec3Df Vel, PJBVec3Df RotVel): PJBGLModel2D(texture,MeshPath,Pos.x,Pos.y,Vel.x,Vel.y,RotVel.x,RotVel.y)
{
	Physics.SetPos(Pos);
	Physics.SetVel(Vel);
	Physics.SetRotVel(RotVel);
}

//High Level model parent constructor

PJBGLModel2D::PJBGLModel2D(PJBGLTexture* texture, char* MeshPath, float Xpos, float Ypos, float XVel, float YVel, float XRotVel, float YRotVel)
{
	Properties.PJBEnable(PJBObjRender);
	LocalMesh=true;
	LocalCompiled=true;
	Mesh = new PJBGLModelMesh(texture,MeshPath);
	DisplayObject = new PJBGLModelCompiled(Mesh);
	if(Mesh)MeshLoaded=true;
	if(DisplayObject)MeshCompiled=true;
	Physics.SetPos(Xpos,Ypos);
	Physics.SetVel(XVel,YVel);
	Physics.SetRotVel(XRotVel,YRotVel);
}

//Note, the memory allocation error occours on the DisplayObject = //new line, however I'm unsure if the address it reports is being //allocated on that line or the line previous...

//Low level model initialiser

PJBGLModelMesh::PJBGLModelMesh(PJBGLTexture* Texture, char* MeshPath)
{
    ModelTexture=NULL;
    ModelMesh=NULL;
    ModelTexture=Texture;
    ModelMesh = PJBLoadObjMesh(MeshPath);
}

//That section doesn't trigger any errors and it seems to be working //fine (checked with breakpoints etc)

//Compiled model initialiser

PJBGLModelCompiled::PJBGLModelCompiled(PJBGLModelMesh *CompileObj)
{
	Compiled=CompileMesh(CompileObj);
	Mesh = CompileObj;
}

The strange part is the previous section never gets called! it seems the failure happens on the 'new' statement inself!

I checked my memory usage and it doesn't appear to be going beyond 20%, I can't understand why it's failing to allocate memory.

Just as a final note the functions worked absolutely fine when using my previous (NeHe inspired) model loading system. For reference I'll post that below.

PJBStdMesh* PJBLoadRawMesh(char* MeshFilePath)
{
    FILE* TheMeshFile;
    TheMeshFile = fopen(MeshFilePath, "rt");
    int numtriangles;           // Number Of Triangles In Sector
    char oneline[255];           // String To Store Data In
    float x,y,z,u,v;
    PJBStdMesh* Mesh;
    PJBStdTriangle* TriangleBuffer;
    if(TheMeshFile)
    {
        Mesh = new PJBStdMesh;
        readstr(TheMeshFile,oneline);         // Get Single Line Of Data
        sscanf(oneline, "NUMPOLLIES %d\n", &numtriangles); // Read In Number Of Triangles
        TriangleBuffer = new PJBStdTriangle[numtriangles];
        Mesh->NumTri=numtriangles;
        for(int TriLoop=0; TriLoop < numtriangles; TriLoop++)
        {
            for(int VertLoop=0; VertLoop < 3; VertLoop++)
            {
                readstr(TheMeshFile,oneline);         // Get Single Line Of Data
                sscanf(oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v);
                TriangleBuffer[TriLoop].Vertex[VertLoop].X=x;
                TriangleBuffer[TriLoop].Vertex[VertLoop].Y=y;
                TriangleBuffer[TriLoop].Vertex[VertLoop].Z=z;
                TriangleBuffer[TriLoop].Vertex[VertLoop].U=u;
                TriangleBuffer[TriLoop].Vertex[VertLoop].V=v;
            }
        }
        fclose(TheMeshFile);
    }
    else
    {
        fclose(TheMeshFile);
        return NULL;
    }
    Mesh->Polygons=TriangleBuffer;
    return Mesh;
}

Now I will admit that the originally loaded models where not very complex, (10-50 polygons at most) meanwhile the OBJ model is quite complex (1500 polygons).
For further reference here are two sample model files.

Original test model (NeHe format)

NUMPOLLIES 6

-1 -1 0 0 0
1 -1 0 1 0
1 1 0 1 1

1 1 0 1 1
-1 1 0 0 1
-1 -1 0 0 0

1 1 0 1 0
1 -1 0 0 1
2 -2 1 0 0

2 -2 1 0 0
2 2 1 1 0
1 1 0 1 0

-1 -1 0 0 1
-2 -2 1 0 0
2 -2 1 1 0

2 -2 1 1 0
1 -1 0 1 1
-1 -1 0 0 1

New model (Obj Format, is rather large, so I've added it as an attachment.)

Finally I realise no one has any interest in 'stealing' my (rather poor) code, however if you do for some unbeknown reason use it, please credit myself and NeHe.

Recommended Answers

All 5 Replies

A tiny update, having checked the memory addresses though thoughtfully the error is being caused by the 'displayobject = new line' not the mesh line above it. Still confused and disoriented! :(

Lessons in cause and effect.

Memory is allocated from one (or more) larger pools of memory.

int main ( ) {
    int *p = new int[10];
    for ( int i = 0 ; i <= 10 ; i++ ) p[i] = 0;  // overrun!!
    double *q = new double[1000];  // exception POSSIBLE here
    /// more code
    delete [ ] q; // exception POSSIBLE here
    delete [ ] p; // exception POSSIBLE here
    return 0;
}

Depending on how badly you screwed up, you may not even get to notice that there is a problem (the program behaves as expected, despite the bugs).

More likely, you make some totally unrelated change in another part of the system and that change immediately blows up in your face (you're confused now right?).

Say the exception happens on the green line of code, how do you get back to the red line of code where the real problem is?
Well, that's a tricky one.
http://msdn.microsoft.com/en-us/library/aa298452%28VS.60%29.aspx
Scattering a few _CrtCheckMemory( ); calls through the code, or setting the debug options to do this every 'n' calls would help narrow the gap between effect (where you notice) and cause (what you need to find and fix).

There are tools for windows (for $$$$$) which can help with this.
Shame really, the tools for this on Linux are available for $0.

> //error checking, saves your ****!
This made me laugh.
I lost count of the number of places where your ass is flapping in the breeze waiting to be kicked.

Right, I've narrowed down the problem further any now have an idea as to where it is. Yet it seems to make even less sense.
The memory allocation error does occour on that line, however previous to that I get the following errors in the debug console:

First-chance exception at 0x7c91a5d3 in Engine Concept.exe: 0xC0000005: Access violation writing location 0x3daad70e.
Heap corruption detected at 01731008
First-chance exception at 0x7c9109f9 in Engine Concept.exe: 0xC0000005: Access violation reading location 0x3daad70e.
First-chance exception at 0x7c91a5d3 in Engine Concept.exe: 0xC0000005: Access violation writing location 0x3daad70e.

The intresting part is this occours between the mesh pointer being returned in PJBLoadObjMesh(), and it being assigned to the pointer in the class init.

}
    else
    {
        fclose(TheMeshFile);
        return NULL;
    }
    return Mesh; //mesh pointer is returned here,
}
ModelMesh = PJBLoadObjMesh(MeshPath); // line where returned mesh pointer should be set to return value.

What I don't understand is why is any heap corruption etc occouring in simply assigning a pointer?
If it's happening previously why is no error generated then? and where in LoadObjFile is it happening and why?
The confusion and disorientation continues like a psyduck!

[edit]
not sure why I missed the above post... but anyhow...

Lessons in cause and effect.

Memory is allocated from one (or more) larger pools of memory.

Depending on how badly you screwed up, you may not even get to notice that there is a problem (the program behaves as expected, despite the bugs).

More likely, you make some totally unrelated change in another part of the system and that change immediately blows up in your face (you're confused now right?).

yes and no, I see what you mean but am scared by the implication.

Say the exception happens on the green line of code, how do you get back to the red line of code where the real problem is?
Well, that's a tricky one.
http://msdn.microsoft.com/en-us/library/aa298452%28VS.60%29.aspx
Scattering a few _CrtCheckMemory( ); calls through the code, or setting the debug options to do this every 'n' calls would help narrow the gap between effect (where you notice) and cause (what you need to find and fix).

There are tools for windows (for $$$$$) which can help with this.
Shame really, the tools for this on Linux are available for $0.

I'll take a look though the memory calls and alike while I cry at my lack of Linux development!

> //error checking, saves your ****!
This made me laugh.
I lost count of the number of places where your ass is flapping in the breeze waiting to be kicked.

Yeah.. so did I, leading to those statements when it bugged out there several times.

So use the debugger and put a breakpoint at the start of where you suspect the problem starts, and then wait for the first of the "first chance exceptions" to happen.

Then home in on the problem.

So use the debugger and put a breakpoint at the start of where you suspect the problem starts, and then wait for the first of the "first chance exceptions" to happen.

Then home in on the problem.

I did, and with the help of those memory commands found the exact cause, I (being a moron) was overrunning my vector by one unit. In short I forgot that var[10] = 0-9.

...I feel so stupid.
=goes to cry=
Anyhow thanks for your help salem!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.