Jump to content
  • Advertisement
Sign in to follow this  
rogierpennink

Runtime error at virtual function call

This topic is 3793 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm experiencing a rather strange run-time error (an access violation) in a certain function where I call another, virtual, function. First things first, so here's the generic error message that Visual Studio 2005 gives:
Unhandled exception at 0x0045697f in u3dtest.exe: 0xC0000005: Access violation reading location 0x3f800004.
The error happens at a line where I call the lock() function (which is virtual) on a ColorBuffer object. I call this function in the BoxGeometry::create() function, so let me paste the relevant parts of that function in here:
void BoxGeometry::create()
{
// Snippet Removed
	if ( this->cb )
	{
		/* Specify colors. */
		Color colors[] =
		{
			Color( color.r, color.g, color.b, color.a ),
			Color( color.r, color.g, color.b, color.a ),
			Color( color.r, color.g, color.b, color.a ),
			Color( color.r, color.g, color.b, color.a ),

			Color( color.r, color.g, color.b, color.a ),
			Color( color.r, color.g, color.b, color.a ),
			Color( color.r, color.g, color.b, color.a ),
			Color( color.r, color.g, color.b, color.a ),
		};

		/* Add colors to colorbuffer. The error occurs on cb->lock(). */
		cb->lock();			// Virtual function call
		cb->addColors( colors, 8 );	// Virtual function call
		cb->unlock();			// Virtual function call
	}
// Snippet removed
}
Now, this may indicate that the pointer to ColorBuffer (cb) is simply invalid, but due to the following experiment I doubt that. Let me elaborate. The BoxGeometry::create function is called from another function that is supposed to create geometry for a simple cube. To do this, it requests a new vertex, index and color buffer from my renderer and then passes those on to the BoxGeometry object. I have verified that I can call the lock() and unlock() functions before I pass the colorbuffer object into the BoxGeometry object. I'll just paste the renderer::createBox function here to show that:
BoxGeometry* U3DRenderer::createBox( float width, float height, float depth )
{
	/* First, request an index and a vertex buffer. */
	IndexBuffer* ib = this->createIndexBuffer( 36 );				// Box needs 36 indices
	VertexBuffer* vb = this->createVertexBuffer( 8, BT_STATIC );	// Box has 8 vertices
	ColorBuffer* cb = this->createColorBuffer( 8, BT_STATIC );		// Box has 8 vertices

	cb->lock();			// No problems at all here
	cb->unlock();
		
	/* Create the box geometry with requested values. */
	BoxGeometry* box = new BoxGeometry( vb, width, height, depth );

	/* Assign vertex/index buffers. */
	box->setColorBuffer( cb );
	box->setIndexBuffer( ib );

	box->dummy();

	/* Since BoxGeometry now has space for the vertices and indices, we can create the geometry. */
	box->create();

	return box;
}
As you can see, I call cb->lock() and cb->unlock() for debugging purposes and nothing happens; virtual functions are no problem. Now the weird part. Because cb seems to be a perfectly valid pointer I figured I'd add a 'dummy' function to the BoxGeometry class that calls exactly the same (virtual) methods as the BoxGeometry::create function. You can see that I call that dummy function right before I call the create function. Strangely enough, the pointer is still valid inside the dummy function as well. I can call both lock() and unlock() without a problem. Only inside the create() function does the lock() call (in fact, any call of a virtual function of the ColorBuffer object) fail. I'm completely lost. I have no idea how this is possible. Would anyone be able to explain why this might happen?

Share this post


Link to post
Share on other sites
Advertisement
Hmm, Are you sure the pointer hasn't been deleted prior to being used? What is the value of the cb pointer? 0x3f800004 doesn't look like a valid heap or stack pointer to me, it's way too high.

Are you doing a debug build? It should crap all over the heap on delete calls to make bugs like that easy to spot.

Another possiblity is a buffer overflow or something I suppose.

Share this post


Link to post
Share on other sites
Yes, I forgot to mention that the pointer doesn't get deleted anywhere. There is only one place where the buffer gets deleted and that is in the BoxGeometry's base class destructor. For certainty, I've put in a simple messagebox call in that destructor and it doesn't seem to be called before this error occurs.

Also, this is a debug build.

Share this post


Link to post
Share on other sites
Not of the ColorBuffer class. All I do is create a new instance using 'new' and passing the resulting pointer around. But what really boggles my mind is that no other operations occur between the dummy() function and the create() function and that the trouble only starts in the create() function. How can a pointer become invalid in such a short time-frame?

Share this post


Link to post
Share on other sites
I just attempted the following:

I commented out the call to BoxGeometry::create and then did:
box->getColorBuffer()->lock();
box->getColorBuffer()->unlock();
So the createBox function now looks like this:
BoxGeometry* U3DRenderer::createBox( float width, float height, float depth )
{
/* First, request an index and a vertex buffer. */
IndexBuffer* ib = this->createIndexBuffer( 36 ); // Box needs 36 indices
VertexBuffer* vb = this->createVertexBuffer( 8, BT_STATIC ); // Box has 8 vertices
ColorBuffer* cb = this->createColorBuffer( 8, BT_STATIC ); // Box has 8 vertices

/* Create the box geometry with requested values. */
BoxGeometry* box = new BoxGeometry( vb, width, height, depth );

/* Assign vertex/index buffers. */
box->setColorBuffer( cb );
box->setIndexBuffer( ib );

box->dummy();

/* Since BoxGeometry now has space for the vertices and indices, we can create the geometry. */
//box->create();

box->getColorBuffer()->lock();
box->getColorBuffer()->unlock();

return box;
}


Again, there are no problems running it. It seems that it has something to do with the create function, but since the dummy function works and contains the same virtual function calls on the colorbuffer object I am left flabbergasted as to why it would fail in the create() function...

Share this post


Link to post
Share on other sites
Certainly, here they are:
class BaseGeometry : public Rtti
{
public:
/* Constructor and virtual destructor. */
BaseGeometry();
BaseGeometry( GeometryType gt );
BaseGeometry( GeometryType gt, VertexBuffer* vb );
virtual ~BaseGeometry();

/* Getters and Setters. */
inline VertexBuffer* getVertexBuffer() { return vb; }
inline void setVertexBuffer( VertexBuffer *v ) { this->vb = v; }
inline IndexBuffer* getIndexBuffer() { return ib; }
inline void setIndexBuffer( IndexBuffer *i ) { this->ib = i; }
inline ColorBuffer* getColorBuffer() { return cb; }
inline void setColorBuffer( ColorBuffer *c ) { this->cb = c; }
inline GeometryType getGeometryType() { return this->gType; }

/* Information. */
inline bool usesIndices() { return ib ? true : false; }
inline bool usesColors() { return cb ? true : false; }

/* Return rtti information. */
virtual std::string getClassname() { return "BaseGeometry"; }

protected:

VertexBuffer* vb;
IndexBuffer* ib;
ColorBuffer* cb;

GeometryType gType;
};


class BoxGeometry : public BaseGeometry
{
public:
/* Default constructor. */
BoxGeometry();
/* Constructor taking a VertexBuffer as argument. */
BoxGeometry( VertexBuffer* v );
/* Constructor taking a VertexBuffer and 3 dimensions for the box as arguments. */
BoxGeometry( VertexBuffer* v, float width, float height, float depth );
/* Virtual destructor. */
virtual ~BoxGeometry();

/* BoxGeometry public interface. */
void setDimensions( float width, float height, float depth );
void create();
void dummy();

/* Getters. */
inline float getWidth() { return width; }
inline float getHeight() { return height; }
inline float getDepth() { return depth; }
inline Color getColor() { return color; }

/* Setters. */
inline void setColor( Color& c ) { color = c; }

/* Return rtti information. */
std::string getClassname() { return "BaseGeometry.BoxGeometry"; }

private:
Color color; // Box color
float width; // Length along the x-axis
float height; // Length along the y-axis
float depth; // Length along the z-axis
bool isCreated; // Has the object already been created?
};

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!