Sign in to follow this  
clum

Segmentation fault in simple crystal space program

Recommended Posts

clum    217
So, for all of you proffessed CS experts: I tried following one of CS's tutorials. I basically copied and pasted the code, but leaving out all the fancy OOP stuff. But I get a segmentation fault when I hit escape gdb says the segmentation fault is taking place in ~csRef(). What did I do wrong? Here's the code:
#include "cssysdef.h"
#include "csutil/sysfunc.h"
#include "iutil/vfs.h"
#include "csutil/cscolor.h"
#include "cstool/csview.h"
#include "cstool/initapp.h"
#include "iutil/eventq.h"
#include "iutil/event.h"
#include "iutil/objreg.h"
#include "iutil/csinput.h"
#include "iutil/virtclk.h"
#include "iengine/sector.h"
#include "iengine/engine.h"
#include "iengine/camera.h"
#include "iengine/light.h"
#include "iengine/texture.h"
#include "iengine/mesh.h"
#include "iengine/movable.h"
#include "iengine/material.h"
#include "imesh/thing.h"
#include "imesh/object.h"
#include "ivideo/graph3d.h"
#include "ivideo/graph2d.h"
#include "ivideo/texture.h"
#include "ivideo/material.h"
#include "ivideo/fontserv.h"
#include "igraphic/imageio.h"
#include "imap/parser.h"
#include "ivaria/reporter.h"
#include "ivaria/stdrep.h"
#include "csutil/cmdhelp.h"
#include "csutil/event.h"

CS_IMPLEMENT_APPLICATION

iObjectRegistry* object_reg;

bool HandleEvent (iEvent& ev)
{
  if (ev.Type == csevKeyboard && 
    csKeyEventHelper::GetEventType (&ev) == csKeyEventTypeDown &&
    csKeyEventHelper::GetCookedCode (&ev) == CSKEY_ESC)
  {
    csRef<iEventQueue> q (CS_QUERY_REGISTRY (object_reg, iEventQueue));
    if (q)
      q->GetEventOutlet()->Broadcast (cscmdQuit);
    return true;
  }
  return false;
}

int main(int argc, char const* argv[]) {
    csRef<iEngine> engine;
    csRef<iLoader> loader;
    csRef<iGraphics3D> g3d;
    csRef<iKeyboardDriver> kbd;
    csRef<iVirtualClock> vc;

    object_reg =
    csInitializer::CreateEnvironment (argc, argv);

    if (!csInitializer::RequestPlugins (object_reg,
					CS_REQUEST_VFS,
					CS_REQUEST_OPENGL3D,
					CS_REQUEST_ENGINE,
					CS_REQUEST_FONTSERVER,
					CS_REQUEST_IMAGELOADER,
					CS_REQUEST_LEVELLOADER,
					CS_REQUEST_REPORTER,
					CS_REQUEST_REPORTERLISTENER,
					CS_REQUEST_END)) {
	csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
		  "crystalspace.application.simple",
		  "Can't initialize plugins!");
	throw 1;
    }

    if (!csInitializer::SetupEventHandler(object_reg, HandleEvent)) {
	
	csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
		  "crystalspace.application.simple",
		  "Can't initialize event handler!");
	throw 1;
    }
    
    // Check for commandline help.
    if (csCommandLineHelper::CheckHelp (object_reg)) {
	
	csCommandLineHelper::Help (object_reg);
	throw 1;
    }

    // The virtual clock.
    vc = CS_QUERY_REGISTRY (object_reg, iVirtualClock);
    if (!vc) {
	csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
		  "crystalspace.application.simple",
		  "Can't find the virtual clock!");
	throw 1;
    }

    // Find the pointer to engine plugin
    engine = CS_QUERY_REGISTRY (object_reg, iEngine);
    if (!engine) {
	csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
		  "crystalspace.application.simple",
		  "No iEngine plugin!");
	throw 1;
    }

    loader = CS_QUERY_REGISTRY (object_reg, iLoader);
    if (!loader) {
	csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
		  "crystalspace.application.simple",
		  "No iLoader plugin!");
	throw 1;
    }

    g3d = CS_QUERY_REGISTRY (object_reg, iGraphics3D);
    if (!g3d) {
	csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
		  "crystalspace.application.simple",
		  "No iGraphics3D plugin!");
	throw 1;
    }
    
    kbd = CS_QUERY_REGISTRY (object_reg, iKeyboardDriver);
    if (!kbd) {
	csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
		  "crystalspace.application.simple",
		  "No iKeyboardDriver plugin!");
	throw 1;
    }

    // Open the main system. This will open all the previously
    // loaded plug-ins.
    if (!csInitializer::OpenApplication (object_reg)) {
	csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
		  "crystalspace.application.simple",
		  "Error opening system!");
	throw 1;
    }
    
    csReport (object_reg, CS_REPORTER_SEVERITY_NOTIFY,
	      "crystalspace.application.simple",
	      "Simple Crystal Space Application version 0.1.");

    csDefaultRunLoop (object_reg);
    csInitializer::DestroyApplication (object_reg);
    return 0;
}

Share this post


Link to post
Share on other sites
clum    217
Oh - I just realised - I have slightly more information: The segfault is happenning in csRef<iGraphics3d>::~csRef. Also, the tutorial claims that its supposed to be a blank screen, but I actually get bits and pieces from old runs of crystal space programs (particularly walktest).

Share this post


Link to post
Share on other sites
clum    217
As an experiment, I tried following the next stage of the tutorial, where you're supposed to draw something, and it came up with a new segfualt, this time directly in main(). I would try compiling with more debugging information to find out exactly where it is, but I have to go now and I'd imagine it is somewhere around when the iGraphics object is first referenced.

Share this post


Link to post
Share on other sites
Erluk    170
You get this problem because you left out the "fancy OOP stuff":

Before you call csInitializer:: DestroyApplication, you have to make sure you released all your references to CS' internal system such as iGraphics3D, iKeyboard etc. In the tutorial, all csRefs are members of the class Simple, so the following code will make sure all references are released before the call to DestroyApplication:


delete simple; // Release engine, loader, g3d, kbd, vc
simple = 0;

csInitializer::DestroyApplication (object_reg);


Solution: change the end of main () to:

csDefaultRunLoop (object_reg);

// add this
engine = NULL;
loader = NULL;
g3d = NULL;
kbd = NULL;
vc = NULL;

csInitializer::DestroyApplication (object_reg);
return 0;


You might also want to read CS Manual: HOWTO Smart Pointers , especially the last paragraph.

edit: changed the CS Manual link to point to the online docs instead of my harddrive

[Edited by - Erluk on July 7, 2004 9:09:24 AM]

Share this post


Link to post
Share on other sites
clum    217
Thanks, that worked. I'm just a bit concerned that the tutorial I read said that I should see a blank screen while I'm seeing gibberish, but hopefully its just that the author of the tutorial had a video card that clears its memory first.

The link you gave is a link to a file on your hard drive, though[grin]. I'm sure I'll manage to find it on mine, though (I don't even have a C:\ drive. In fact, that would be an illegal drive specification in my operating system.)

Share this post


Link to post
Share on other sites
Erluk    170
Quote:
Original post by clum
The link you gave is a link to a file on your hard drive, though[grin].


Whoops, that's why you shouldn't have online and offline documentation opened at the same time... [rolleyes]

Anyway, this should be the correct link: CS Online(!) Manual

Share this post


Link to post
Share on other sites
clum    217
In other words, I should just put all of my objects into a class and call csInitializer::DestroyApplication() from somewhere else (like main()). That's fine with me, because I normally use classes heavily, its just that I saw no point in such a simple program.

Share this post


Link to post
Share on other sites
clum    217
Another quick question: The tutorial I was reading has something really strange - it uses a iSector * instead of a csRef<iSector>. Is this intentional? It also doesn't appear to delete or csDecRef it anywhere. That doesn't sound right. Is this a mistake or just something I don't understand. EDIT: There's another, similar pointer in the next stage of the tutorial, too:
iGraphics2D* g2d = g3d->GetDriver2D ();
view->SetRectangle (0, 0, g2d->GetWidth (), g2d->GetHeight ());


[Edited by - clum on July 7, 2004 10:05:01 AM]

Share this post


Link to post
Share on other sites
clum    217
Well, I worked out the g2d one:
Quote:
From the same HOWTO
If you do not need to own a reference to a reference-counted object, and you know positively that the object will exist for the duration of a piece of code, then you can use a plain pointer rather than a smart pointer.
I'm still suspicious about that iSector *, though.

Share this post


Link to post
Share on other sites
Erluk    170
Perhaps it was just an oversight. But I can't really help you there; maybe one of the CS developers that lurk on these boards knows more... or you could ask on the crystal-main mailing list.

Share this post


Link to post
Share on other sites
acraig    471
I normally use csRef for anything I grab from CS like iGraphics2D. It is the safest way to prevent memory leaks. The easiest way to check stuff like that is to call

object->GetRefCount() to see how many things are accessing it.

If at the end you keep getting stuff like "Unreleased references" you can use the GetRefCount() to track them down ( painful sometimes ).


The example you show with iSector is ok since it is just a plain pointer so unless you do an IncRef on it you don't need a DecRef.

Edit: Update with correct info :)
---------
Andrew

[Edited by - acraig on July 8, 2004 9:06:28 AM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this