Pointers losing their type?

Started by
18 comments, last by Shamino 18 years, 4 months ago
Okay, let me clear a few things up before I give you any code. Number 1, I'm using 1 pointer to a single model on both draw attempts. (could be problem #1) Number 2, There ARE two things in the Scene_Objects vector. Number 3, Both objects return the same pointer to the same Model. Numebr 4, This works with only 1 Object in Scene_Objects.

void GLRenderer::DrawSceneObjects()
{
	for (int i = 0; i<Scene_Objects.size(); i++)
	{	
		Obj = Scene_Objects->GetRenderInformation();
		GLRenderer::Draw(Obj);
		Obj = NULL;
		glTranslatef(0.0, 0.0, -30.0);
	}
}

I get a nasty error on this one, no compiler errors, just errors during runtime. Any clues? I can run the debugger sure, but I have no idea what to look for. [Edited by - Shamino on December 19, 2005 11:13:58 PM]
----------------------------------------------------------Rating me down will only make me stronger.----------------------------------------------------------
Advertisement
You could start by describing the errors you get...

Then fire up the debugger and at least figure out what line it's terminating on.

Then examine the state of your variables, containers, etc at the time of the crash and figure out what it's trying to do that's causing it to crash, then figure out what would cause it to try and do such a thing. Basic debugging and troubleshooting skills, you need to apply.
Okay, so the error is this, ran debugger, I'll ignore how rude you were.

Basically, the second go around, the program can't figure out what Obj's model information is, why are we losing this information our second go around?

Here is my Model Loading code, it works the first time, but the second time around, it breaks.... Should I set Obj to Null before I start this function each time?
void GLRenderer::Draw(MS3DModel * Obj){ 	GLboolean texEnabled = glIsEnabled( GL_TEXTURE_2D ); 	// Draw by group	for ( int i = 0; i < Obj->NumMeshes; i++ )	{ 		int materialIndex = Obj->Meshes.MaterialIndex;		if ( materialIndex >= 0 )		{			glMaterialfv( GL_FRONT, GL_AMBIENT, Obj->Materials[materialIndex].Ambient );			glMaterialfv( GL_FRONT, GL_DIFFUSE, Obj->Materials[materialIndex].Diffuse );			glMaterialfv( GL_FRONT, GL_SPECULAR, Obj->Materials[materialIndex].Specular );			glMaterialfv( GL_FRONT, GL_EMISSION, Obj->Materials[materialIndex].Emissive );			glMaterialf( GL_FRONT, GL_SHININESS, Obj->Materials[materialIndex].Shininess ); 			if ( Obj->Materials[materialIndex].Texture > 0 )			{				glBindTexture( GL_TEXTURE_2D, Obj->Materials[materialIndex].Texture );				glEnable( GL_TEXTURE_2D );			}			else				glDisable( GL_TEXTURE_2D );		}		else		{			// Material properties?			glDisable( GL_TEXTURE_2D );		} 		glBegin( GL_TRIANGLES );		{			for ( int j = 0; j < Obj->Meshes.NumTriangles; j++ )			{				int triangleIndex = Obj->Meshes.TriangleIndices[j];				const MS3DModel::Triangle * pTri = &(Obj->Triangles[triangleIndex]); 				for ( int k = 0; k < 3; k++ )				{					int index = pTri->VertexIndices[k]; 					glNormal3fv( pTri->VertexNormals[k] );					glTexCoord2f( pTri->Textures1[k], pTri->Textures2[k] );					glVertex3fv( Obj->Vertices[index].Location );				}			}		}		glEnd();	} 	if ( texEnabled )		glEnable( GL_TEXTURE_2D );	else		glDisable( GL_TEXTURE_2D );}


Let me give you the exact messages the debugger gives me...

	__vfptr	CXX0030: Error: expression cannot be evaluated	NumVertices	CXX0030: Error: expression cannot be evaluated	Vertices	CXX0017: Error: symbol "" not found	NumTriangles	CXX0030: Error: expression cannot be evaluated	Triangles	CXX0017: Error: symbol "" not found	NumMeshes	CXX0030: Error: expression cannot be evaluated	Meshes	CXX0017: Error: symbol "" not found	NumMaterials	CXX0030: Error: expression cannot be evaluated	Materials	CXX0017: Error: symbol "" not found


That happens right when I call my Draw function the second time.
----------------------------------------------------------Rating me down will only make me stronger.----------------------------------------------------------
To generally avoid problems like this, it is best to narrow the possibilities as much as possible. I would suggest you to qualify all suitable variables "const", in this case e.g.
void GLRenderer::Draw(const MS3DModel * Obj)
since the Draw routine isn't expected to alter the model. Also make all local variable inside the Draw method const where possible.

Next, it would be good to check routine parameters for correctness by assertions, in this case e.g.
void GLRenderer::Draw(MS3DModel * Obj){    // checking requirements    assert(Obj != 0);    ...

Stuff like this has the advantage to point out mistakes that would have an effect here but are made elsewhere!

Unfortunately, the posted debugger output isn't helpful (at least to me). To use the debugger best in your case, you have to investigate the situation just _before_ the error happens. So, start the debugger, set a breakpoint at the line
GLboolean texEnabled = glIsEnabled( GL_TEXTURE_2D );
and run the program. When the debugger stops at the marked line the first time, you have the ability to look at the variable states "how they should be" during stepping through the routine. However, you could also simply "continue" that first stop if you know how the variables should look like. Then the debugger will stop the second time at the marked line. Compare the available variables by the values you expect. At any point a difference will occur.


What I'm curious about is that the DrawSceneObjects() routine uses a copy of Obj from the GetRenderInformation() method, and the Draw(MS3DModel*) uses a pointer to a MS3DModel. Since not visible from the given code snippets, I assume that there is a type compatibility like
typedef MS3Model* Obj
or something equivalent?


Quote:Original post by Shamino
Should I set Obj to Null before I start this function each time?

No.
"Expression cannot be evaluated" sounds more like something that would come up in the expression watch window than an actual error. This is straight C++ not Managed C++ right? I can't see anything in GLRenderer::Draw which writes to anything so I don't think it's in there. I suggest watching the contents of Obj all the way through both functions (try watching *(MS3DModel*)0xits_address).
My Programming teacher suggested I investigate the "this" operator, apparently Obj loses access to its class the second time around, all those things that are unable to be determined are model information.

Here is a quote from my book that interests me.

Right now we can assume that Obj will become = to the same pointer, but not always, so we can't const it..

"Sometimes you need to find the class of an object. You may wonder how you could lose track of an object's class. However, imagine that you have an array of pointers to objects, and these pointers may point to objects of several different derived classes. How do you know what kind of object a pointer points to? We know we can use such a pointer to call a virtual function for the object, and the appropriate function will be called, depending on the type of object. The virtual function mechanism knows what kind of object the pointer points to, However, this information is not immediately available to the programmer."

Sounds like my problem, I think the problem is that Obj is losing its class.

How to remedy this?
----------------------------------------------------------Rating me down will only make me stronger.----------------------------------------------------------
this is not an operator. In non-static member functions it's a pointer to the class the function was called on. Therefore in both DrawSceneObjects and Draw the this pointer will point to the GLRenderer object if those functions are not static (DrawSceneObjects appears to be non-static, as for Draw I can't tell).

I'm sorry to say this but going by the posted code I simply can't see how the Obj pointer can be the same both times Draw is called - that is, I think the Obj pointer is incorrect the second time, but that would be an error elsewhere in the code. If it is the same then it should work since the Draw function doesn't set anything except local variables.
Quote:Original post by Shamino
Right now we can assume that Obj will become = to the same pointer, but not always, so we can't const it..

Hmm? Could you please post the line defining Obj? I assume Obj to be of a class derived from MS3Model, right?

Quote:Original post by Shamino
"Sometimes you need to find the class of an object. You may wonder how you could lose track of an object's class. However, imagine that you have an array of pointers to objects, and these pointers may point to objects of several different derived classes. How do you know what kind of object a pointer points to? We know we can use such a pointer to call a virtual function for the object, and the appropriate function will be called, depending on the type of object. The virtual function mechanism knows what kind of object the pointer points to, However, this information is not immediately available to the programmer."

Sounds like my problem, I think the problem is that Obj is losing its class.

That is unlikely. SceneObjects is an array of pointers to a class (you haven't told us yet) that provides a method GetRenderInformation() returning something of the Obj's type. You copy the result to Obj in the DrawSceneObjects. If there would be really a problem in that, the compiler would complain and you wouldn't get an executable.

It is true that you as a programmer may not have an immediate possibility of checking for an object's type, but that isn't true for the compiler. A compiler will (hopefully) complain all type mismatches in advance.

I still suggest you to do an assertion on the local Obj inside Draw! As I already stated above (and also ZQJ has) it is likely that the problem isn't in the code snippets you have posted but elsewhere.
First off, I put a check to see if Obj = 0, it still runs, therefore Obj is filled up both times, it is pointing to something, but its broken the second time around?

Nothing else in my code works with this functions, theres four things that work together to create images on my screen.

Draw, DrawSceneObjects, the vector of objects, and MS3DModel.

Obj is declared as MS3DModel * Obj; (switched this to const)
Ship1 (element 0 in the array) is declared as Ship * Ship1;
Ship2 (element 1 in the array) is declared as Ship * Ship2;

We fill up the vector manually in initgl (this is where we push_back Ship1/2 into the vector. We declare Ship1/2 as extern after the declaration of Ship.

Now we have a vector of two Ship objects, both of these have the GetRenderInformation() method, which returns a pointer to an MS3DModel;

we go to our DrawSceneObjects function, which loops through the vector activating each ship objects getrenderdata function, this returns an ms3dmodel pointer.

We set that pointer equal to Obj, we pass Obj to the Draw function, Obj is drawn according to what was returned by the getrenderdata method.

Same process happens again, until finally we begin to try to draw the second Obj, while this time it can't figure out any information specific to itself, it doesn't know how many vertices, how many anything, Obj can simply not access its own data.... Either that, or Obj wasn't set to getrenderdata's return type correctly, but it was the first time?

I'll give the MS3DModel class to you guys.
#ifndef MS3D_H#define MS3D_H#include <windows.h>																						#include <gl\glaux.h>						#include <vector>class MS3DModel{public:	MS3DModel();	virtual ~MS3DModel();	struct Vertex	{		char BoneID;		float Location[3];	};	int NumVertices;	Vertex *Vertices;	struct Triangle	{		float VertexNormals[3][3];		float Textures1[3], Textures2[3];		int VertexIndices[3];	};	int NumTriangles;	Triangle *Triangles;	struct Mesh	{		int MaterialIndex;		int NumTriangles;		int *TriangleIndices;	};	int NumMeshes;	Mesh *Meshes;	struct Material	{		float Ambient[4], Diffuse[4], Specular[4], Emissive[4];		float Shininess;		GLuint Texture;		char *TextureFilename;	};	int NumMaterials;	Material *Materials;	bool LoadModelData( const char *filename );	void ReloadTextures();	void DrawMS3DModels();};#endif


Could there possibly be something wrong with my Draw function?

I tried to make it Obj specific, whatever Obj equals is drawn..
----------------------------------------------------------Rating me down will only make me stronger.----------------------------------------------------------
Anyone have a clue?

What was that about typedef haegarr?

I set everything possibly to const in the draw function, as well as an if statement checking to see if Obj != 0....
----------------------------------------------------------Rating me down will only make me stronger.----------------------------------------------------------

This topic is closed to new replies.

Advertisement