Skip to main content
GameDev.net gamedev.net
🔒 Locked 🎮 Unity

[Cause Found] StackOverflow Error but how ?

Started by Xrystal Aug 13, 2006 at 10:44 AM 3 replies 450+ views
Original Post
Xrystal
Xrystal
After getting the rotation finally working (kinda - probably needs some more maths calculations) I noticed that my cameras and primitives had identical code relating to their information in World Space. So I thought I would create a WorldObject class that they could both be based on. So a recap on the hierarchy of the classes I have: DXWorld - holds the x, y, z position and deals with the matrices for the object DXWorldObject - talks to the DXWorld class and handles orbiting manouvers and setting of the world information DXPrimitive - the base class for drawing primitives on the screen DXPrimitiveList - an ArrayList of Primitives DXCamera - nuff said DXCameraList - an ArrayList of Cameras DXWorld-DXWorldObject-DXCamera DXWorld-DXWorldObject-DXPrimitive object variables used in the program m_CamPrimList = List of Primitives that are the Camera's visual element m_CameraList = List of Cameras m_PrimitiveList = List of Primitives Steps I took to convert from a non WorldObject class program. Compiled and run after each step. I didn't continue until I saw it working as expected. 1. Create WorldObject and teach it about World 2. Adjust Camera to use WorldObject and its related code in the main program 3. Adjust Primitive to use WorldObject and its related code in the main program At this point it fails when drawing the primitives I'll try and post the code in, in the order it executes: First we make sure we are using updated world information. This and the block of code after are executed in that order.

for (int i = 0; i < m_CameraList->Count - 1; i++)
{	
  m_CameraList->Camera->LookAt = m_PrimitiveList->Primitive->WorldCoords;
  m_CameraList->Camera->OrbitalCenter = m_PrimitiveList->Primitive->World;
  m_CameraList->Camera->Orbit();
}
for (int i = 0; i < m_CamPrimList->Count - 1; i++)
{	
  m_CamPrimList->Primitive->WorldCoords = m_CameraList->Camera->WorldCoords;
  m_CamPrimList->Primitive->OrbitalCenter = m_CameraList->Camera->OrbitalCenter;
  m_CamPrimList->Primitive->Orbit();
}
if (m_ActiveCamera) 
{
  m_ActiveCamera->ActivateView();
}



Then we draw the primitives themselves - in this case my triangles and camerapoints. It never gets as far as CamPrimList->Draw though.

Console::WriteLine("Drawing Primitives");
m_PrimitiveList->Draw(PrimitiveType::TriangleList);
Console::WriteLine("Drawing CameraPoints");
m_CamPrimList->Draw(PrimitiveType::PointList);



The call to PrimitiveLists and CamPrimLists then goes here

void DXPrimitiveList::Draw(PrimitiveType primitiveType)
{
  IEnumerator* ie = m_Primitives->GetEnumerator();
  while(ie->MoveNext())
  {
    Console::WriteLine(String::Format("Drawing Primitive : {0}",__box(dynamic_cast<DXPrimitive*>(ie->Current)->ID)));
    dynamic_cast<DXPrimitive*>(ie->Current)->Draw(primitiveType);
  }
}



It then calls this routine which transforms the object.

bool DXPrimitive::Draw(PrimitiveType primitiveType)
{
  Console::WriteLine("Transforming World with Primitive Coordinates");
  m_device->Transform->World = m_WorldSpace->Transform();
  Console::WriteLine("Do we have a mesh to draw?");
  if (m_mesh) 
  {
    Console::WriteLine("Drawing Mesh");
    m_mesh->DrawSubset(0);
    return true;
  }
  else
  {
    Console::WriteLine("Drawing Primitive");
    return Draw(primitiveType,0,m_vertexCount);
  }
}



The transform call then goes here. It skips over the m_Center test as these objects don't orbit anything and calls the standard Transform code. However it executes the last Console::WriteLine command and displays the information but then fails to return the value calculated on the next line but instead quits out with the StackOverflow error. I can't see why though as it never calls itself without a center point.

Matrix DXWorld::Transform(void)
{
  if (m_Center) 
  {
    Console::WriteLine("Transforming World with a Center");
    return this->m_scale * this->m_rotate * this->m_translate * this->m_Center->Transform();
  }
  Console::WriteLine("Transforming World without a Center");
  Console::WriteLine(String::Format("Scale={0}\n,Rotate={1}\n,Translate={2}\n\n",m_scale.ToString() , m_rotate.ToString() , m_translate.ToString()));
  return  this->m_scale * this->m_rotate * this->m_translate;
}



This is the console output. I've relayed out the Matrix values but not altered their values.

Drawing Primitives
Drawing Primitive : 0
Transforming World with Primitive Coordinates
Transforming World without a Center
Scale=Determinant: 1
M11: 1   M12: 0   M13: 0   M14: 0
M21: 0   M22: 1   M23: 0   M24: 0
M31: 0   M32: 0   M33: 1   M34: 0
M41: 0   M42: 0   M43: 0   M44: 1

,Rotate=Determinant: 1
M11: 1   M12: 0   M13: 0   M14: 0
M21: 0   M22: 1   M23: 0   M24: 0
M31: 0   M32: 0   M33: 1   M34: 0
M41: 0   M42: 0   M43: 0   M44: 1

,Translate=Determinant: 1
M11: 1   M12: 0   M13: 0   M14: 0
M21: 0   M22: 1   M23: 0   M24: 0
M31: 0   M32: 0   M33: 1   M34: 0
M41: 0   M42: 0   M43: 0   M44: 1



As a note the first primitive has Zero coordinates and thus positioned in the center of space. A brief overview of world space links. Camera->Primitive CamPrim->Primitive Primtive->Nothing I could understand if it had a problem with CamPrim transforming and overflowing as it runs the code twice, once for itself and once for its center but this is clearly not the case. As said, the code worked great until I introduced the worldobject class to the primitive class. If anyone can see anything wrong I would be much appreciative. Thanks for reading this loooong post. [Edited by - Xrystal on August 14, 2006 2:09:42 AM]
ToohrVyk
ToohrVyk
What does the call stack look like when the exception occurs? On what line, precisely, does it occur?
Xrystal
Xrystal
Wow, quick reply.

Sorry, forgot to mention the stack trace that. The call stack stops at :

  Console::WriteLine("Transforming World with Primitive Coordinates");  m_device->Transform->World = m_WorldSpace->Transform();


Which enabled me to track down to the Transform code in the DXWorld class, and thus with console output to the last line executed. It just never returns from that call.

When the pop up screen appears this is what it shows inside:
System.NullReferenceException: Object reference not set to an instance of an object.   at Microsoft.DirectX.Direct3D.Device.get_Transform()   at DXPrimitive.Draw(PrimitiveType primitiveType) in c:\documents and settings\xxxxxx\my documents\visual studio projects\managed\idxworld\dxprimitive.cpp:line 172   at DXPrimitiveList.Draw(PrimitiveType primitiveType) in c:\documents and settings\xxxxxx\my documents\visual studio projects\managed\idxworld\dxprimitive.cpp:line 684   at DXForm.Render(Int32 RenderStage) in c:\documents and settings\xxxxx\my documents\visual studio projects\managed\idxworld\dxform.cpp:line 93   at DXForm.OnPaint(Object pSender, PaintEventArgs pArgs) in c:\documents and settings\xxxxxx\my documents\visual studio projects\managed\idxworld\dxform.cpp:line 396   at System.Windows.Forms.Control.OnPaint(PaintEventArgs e)   at System.Windows.Forms.Form.OnPaint(PaintEventArgs e)   at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)   at System.Windows.Forms.Control.WmPaint(Message& m)   at System.Windows.Forms.Control.WndProc(Message& m)   at System.Windows.Forms.ScrollableControl.WndProc(Message& m)   at System.Windows.Forms.ContainerControl.WndProc(Message& m)   at System.Windows.Forms.Form.WndProc(Message& m)   at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)   at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


When I click on quit it shows StackOverflowException in the console window.

Device is a property of the DXBase class that returns the device set up when you first initialise directx. Everything gets that variable passed onto its creation routine. DXWorldObject holds the device for its child classes.

Thanks for the prompt reply. Its probably something stupid I've done but I can't see why the Primitives would have a problem when the Cameras didn't, apart from the fact that they don't get drawn per se.

Hmm, just re-arranged the drawing so that the CamPrimList is drawn first and I get the same problem. It gets to the transform and gets messed up. Even though it has a center point to recall the routine. Just in case it helps this is the console output for drawing the CamPrimList first:

Drawing CameraPointsDrawing Primitive : 0Transforming World with Primitive CoordinatesTransforming World with a CenterTransforming World without a CenterScale=Determinant: 1M11: 1   M12: 0   M13: 0   M14: 0M21: 0   M22: 1   M23: 0   M24: 0M31: 0   M32: 0   M33: 1   M34: 0M41: 0   M42: 0   M43: 0   M44: 1,Rotate=Determinant: 1M11: 1   M12: 0   M13: 0   M14: 0M21: 0   M22: 1   M23: 0   M24: 0M31: 0   M32: 0   M33: 1   M34: 0M41: 0   M42: 0   M43: 0   M44: 1,Translate=Determinant: 1M11: 1   M12: 0   M13: 0   M14: 0M21: 0   M22: 1   M23: 0   M24: 0M31: 0   M32: 0   M33: 1   M34: 0M41: 0   M42: 0   M43: 0   M44: 1


Which definitely points the problem connected with that last return out of the Transform function. Even though that hasn't been changed since I got the rotation code working, just how its accessed.

Edit:

Ah, it helps to talk about problems. Looks like the WorldObject can't have the only link to the device. Had to reinstate the Primitive classes device link and then it drew them.

However, now the rays I create with the Primitive class, as below, has a similar problem. But not the same:

DXWorldObject->DXPrimitive->DXRay

Ah, the problem seems to be related to when the finalising code is executed. Program now runs but when I try to do anything that eventually calls a finalise or dispose routine it causes the stack overflow. I'll have to look into how I should dispose and finalise now it seems to have a problem with my existing code. Thanks again.

[Edited by - Xrystal on August 13, 2006 1:36:42 PM]
ToohrVyk
ToohrVyk
EDIT: your error is in fact that there is an access to a null pointer. Continuing to run the program after this error results in a stack overflow, but that's not really relevant. What's important is what causes the null pointer access.

It seems to occur inside a Direct3D call made from DXPrimitive.Draw(PrimitiveType primitiveType). Can you show the relevant code (and line)?
Xrystal
Xrystal
hehe, you replied while I was editing my last reply.

well that particular problem went away once I made sure that the DXPrimitive class had its own copy of the device back. For some reason it didn't have access to the WorldObject version which its constructor passes along to it.

Now, as I mentioned near the end of that last post it seems that there is a problem with finalising the code. I'm probably finalising something I shouldn't with the classes added.

DXWorld - Finalises its variables (no sub classes)
DXWorldObject - Finalises its variables and calls DXWorld::Dispose
DXPrimitive - Finalises its variables and calls DXWorldObject::Dispose
DXPrimitiveList - Finalises its arraylist variable
DXCamera - Finalises its variables and calls DXWorldObject::Dispose
DXCameraList - Finalises its arraylist variable
DXRay - Finalises its variables and calls DXPrimitive::Dispose

Unless the way I am calling the parent classes dispose routine is wrong I can't see why this isn't working now when it didn't have problems before I added WorldObject class.

I think I may have to have another look at this. See if I missed something out that I shouldn't have or put something in the wrong place. To top it all off the camera points aren't orbiting their objects now either. grr dang it.

edit: Yep, theres lots of stuff no longer working now due to this stack overflow that now seems to occur somewhere else but theres no stack trace.

So far I get it when closing the form and it goes through the finalising code and it gets it when testing intersection by clicking on the screen. However, in that instance it doesn't even get to the start of the MouseDown routine for the form.

I think I totally messed up the code trying to fix DXPrimitive with the new World Object. Definitely time to rethink that rewrite.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.