Game Development Community

Access violation - need help

by Chris \"Hobbiticus\" Weiland · in Torque Game Engine · 05/14/2002 (11:54 am) · 10 replies

I have 2 files doing almost the same thing, but one of the lines of code doesn't work in one and works fine in the other.
objects[i]->getDataBlock()->getName()
seems to be the problem. Objects is defined as
Vector objects;
Is there something I need to do before I call this line? Or is there something that would screw it up?

This file works:
static void findObjectsCallback(SceneObject* obj, S32 val)
{  
   Vector<SceneObject*> * list = (Vector<SceneObject*>*)val;
   list->push_back(obj);
}
void GuiCompassHud::onRender(Point2I offset, const RectI &updateRect)
{
...
   GameConnection* conn = GameConnection::getServerConnection();
   if (!conn) return; //need connection to server
	ShapeBase *control = conn->getControlObject();
	if(!control)
		return;
	MatrixF cam;
	Point3F camPos;
	conn->getControlCameraTransform(0,&cam);
	cam.getColumn(3, &camPos);
	cameraRot = camPos;

   Vector<GameBase*> objects;
	U32 types = ItemObjectType | ShapeBaseObjectType;
   gServerContainer.findObjects(types, findObjectsCallback, (S32)&objects);
   for(U32 i = 0; i < objects.size(); i++)
   {
		Point3F pos = objects[i]->getPosition();
		Point3F posf;
		if (!dStrcmp(objects[i]->getDataBlock()->getName(), "Flag") || !dStrcmp(objects[i]->getDataBlock()->getName(), "FlagImage"))
...
But this doesn't:
static void findObjectsCallback(SceneObject* obj, S32 val)
{  
   Vector<SceneObject*> * list = (Vector<SceneObject*>*)val;
   list->push_back(obj);
}

struct WaypointF
{
		float x;
		float y;
		float z;
		char* name;
		bool mask;
};

void GuiWaypointHud::onRender( Point2I, const RectI &updateRect)
{
	// Must be in a TS Control
   GuiTSCtrl *parent = dynamic_cast<GuiTSCtrl*>(getParent());
   if (!parent) return; //need parent
	
   GameConnection* conn = GameConnection::getServerConnection();
   if (!conn) return; //need connection to server
	ShapeBase* control = conn->getControlObject();
	if (!control) return;
	WaypointF waypointData[20];
   Vector<GameBase*> objects;
   gServerContainer.findObjects(MarkerObjectType, findObjectsCallback, (S32)&objects);

   for(U32 i = 0; i < objects.size(); i++)
   {
		waypointData[count].mask = false;
		if (!dStrcmp(objects[i]->getDataBlock()->getName(), "WayPointMarker")) //Access violation here
...

#1
05/14/2002 (12:22 pm)
Where is MarkerObjectType defined?

gServerContainer.findObjects(MarkerObjectType, findObjectsCallback, (S32)&objects);

Where is offset
void GuiWaypointHud::onRender( Point2I ?, const RectI &updateRect)
offset parameter?

Not much error checking here. I haven't looked at the code extensively but those would be my questions.
#2
05/14/2002 (12:44 pm)
I don't need offset, and MarkerObjectType is defined in objectTypes.h
#3
05/14/2002 (4:22 pm)
MarkerObjectType doesn't seem to have been set from the snippet supplied. ie from example
U32 types = ItemObjectType | ShapeBaseObjectType;

Where are you setting the mask for it?
#4
05/15/2002 (2:19 pm)
The mask is in the function call

For some reason, it works with ItemObjectType, but not MarkerObjectType. Any suggestions of how to get the datablock name?
#5
05/15/2002 (7:49 pm)
Sorry missed that it was already a mask. My guess is that if it works with ItemTypeMask and not the other one then the find for objects only sees ItemType object types. The string function of course will fail if no vaild object pointer finds have been found.
#6
05/15/2002 (8:58 pm)
I think that the code causing the error would not even be executed if no objects are found.

Here's the problem:

findObjectsCallback expects to be dealing with the address of a vector of SceneObject pointers. By giving it the address of a vector of GameBase object pointers instead, you're doing an end-run around the typechecking of C++. You end up with a vector of GameBase object pointers that do not necessarily actually point to GameBase objects.

And in this case, they don't. Unless you've made other changes to the engine in this regard, the MarkerObjectType type bit will be set only for AudioEmitter objects and for Marker objects. AudioEmitter and Marker are both derived from SceneObject, not GameBase, and so neither of those classes have datablocks. When you try to do getDataBlock()->getName() on an object of either of those classes, bad things will happen.
#7
05/16/2002 (2:04 pm)
The thing is, SceneObject has no getDatablock() function. Is there any other way to get the datablock name of marker objects (specifically waypoint datablocks)? Or, would i have to risk writing a getDataBlock() in the SceneObject class?
#8
05/16/2002 (2:22 pm)
No, dont do that :)

here do this:
Make a Named group for your needs ..
Much better :)
then when creating all your objects shove them in your group.
(this looks like a good place for that)

Opps :)
there seems to already be a group for this
ImplementNamedSet(WayPointSet)
so now you just need to be sure your objects are in it.
and use it :)
#9
05/17/2002 (12:03 pm)
whoa whoa whoa...slow down. I don't know the engine all that well, and I'm not an expert on inheritance and data structures. Can you be a little more specific?
#10
05/17/2002 (2:16 pm)
Ok,
here is a code snip in c++ operating a named group:
SimGroup *clientGroup = Sim::getClientGroup();
SimGroup::iterator i;
for(i = clientGroup->begin(); i != clientGroup->end(); i++)
{
         NetConnection *con = (NetConnection *) (*i);
         if(con->isGhosting())
            con->objectInScope(this);
}

find :
../torque/engine/console/simBase.h
line: 511 it starts ..
and:
../torque/engine/console/simBase.cc
line 22

then in that same file find line: 274

what this is doing is creating and instantiating a named group.
so Now in the code you can iterate thru this group.

here is an example in the script:
%count = ClientGroup.getCount();
for (%i = 0; %i < %count; %i++)
{
      %cl = ClientGroup.getObject(%i);
      if( !%cl.isAIControlled() )
         commandToClient( %cl, 'centerPrint', %message, %time, %lines );
}

here is an example in c++ how to add to the group:
SimGroup *g = Sim::getClientGroup();
   g->addObject(client);