FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Exception thrown on program close

 
Post new topic   Reply to topic     Forum Index -> Derelict
View previous topic :: View next topic  
Author Message
RobotGymnast



Joined: 06 Jan 2011
Posts: 23

PostPosted: Thu Jan 20, 2011 7:58 am    Post subject: Exception thrown on program close Reply with quote

My project has been giving me a cryptic "An exception was thrown while finalizing an instance of class classnamehere". I whittled down the code to just this:

Code:
import derelict.sdl.sdl;
import std.stdio;

class SdlInit
{   
   this()
   {
      DerelictSDL.load();
      SDL_Init(SDL_INIT_VIDEO);
   }
   
   ~this()
   {
      writeln("It works up to here...");
      SDL_Quit();           // causes the error
      writeln("It works up to here #2");
      DerelictSDL.unload(); // doesn't cause the error
   }
}

void main()
{
   auto sdlInit = new SdlInit;
}


And it STILL causes the error. The error is in SDL_Quit() somehow, as removing that line causes the error not to occur. I've had this happen with calling SDL_FreeSurface in a destructor. Am I doing something wrong, or is it a bug?

Update: Declaring the class as a scope class fixes the issue, but I don't understand why, nor do I think this should be the case.

What it comes down to is that when I start using Derelict in a project, I have to change a massive number of things, because of the way Derelict unloads itself before the garbage-collector fixes things up. It also means I can either choose to manually deallocate all the allocate class instances, essentially creating my own garbage collector which is Derelict-compatible; or I can refuse to use closures, which are pretty important parts of D.


Last edited by RobotGymnast on Sun Jan 23, 2011 12:18 pm; edited 1 time in total
Back to top
View user's profile Send private message
Stanley Pancakes



Joined: 26 Dec 2009
Posts: 18

PostPosted: Thu Jan 20, 2011 10:07 am    Post subject: Reply with quote

Actually, this is the case. Well, partially, that is.

The reason for this behavior is pretty simple, though not obvious at first glance. You do not manually delete an instance of your class, which means it is left for garbage collector. In this case, collection occurs at program exit, but sadly, after module destructors have been run. derelict.sdl.sdl.~this() calls DerelictSDL.unload(), and at this point, all bindings to SDL functions become invalid. Later, GC chews an instance of your class and calls its' dtor, which happens to call SDL_Quit(). But, as SDL_Quit pointer is already invalid, pretty much anything can occur.
When you made your instance scoped, issue was defeated because dtor was called at exit from main(), before any module dtors were called.
The same, of course, stands for SDL_FreeSurface() calls as well.

Relying on dtor freeing resources in a garbage-collected environment is not a very good idea, because you can't tell precisely when objects are collected (unless you delete them manually), and leads to problems such as this one.

The simplest setup to avoid this kind of issue is to have separate class/module that initializes/quits SDL and tracks all SDL resources allocated by your application. You could then free those resources before calling SDL_Quit().

BTW, as you've already guessed, I'm sure, there is no need to manually call DerelictSDL.unload() at program exit - derelict module dtor will do that for you.
Back to top
View user's profile Send private message
RobotGymnast



Joined: 06 Jan 2011
Posts: 23

PostPosted: Thu Jan 20, 2011 10:44 am    Post subject: Reply with quote

Ah, makes sense. Thanks! I just scoped all the classes whose destructors were nontrivial (i.e. having side-effects like freeing resources).

As for .unload(), I did know that, I was just using it as example code. The original problem actually cropped up in my class managing the screen, which didn't load or quit SDL.
Back to top
View user's profile Send private message
Stanley Pancakes



Joined: 26 Dec 2009
Posts: 18

PostPosted: Thu Jan 20, 2011 11:07 am    Post subject: Reply with quote

One side, off-topic, note. If you're using D2, then scope delcarations are going away from the language. So in this case you're better off with scope(exit). IRC, library replacement was discussed for Phobos, but I can't tell right now whether it exists/works.

Another thing going away is delete operator: it'll be replaced with clear() function. As of now, clear() isn't fully/properly implemented though. So it may be a good choice to move resource deallocation to separate method and use that in conjunction with scope(exit) and on it's own as well, at least until the situation with clear() becomes, uh, clear.
Back to top
View user's profile Send private message
RobotGymnast



Joined: 06 Jan 2011
Posts: 23

PostPosted: Thu Jan 20, 2011 11:08 am    Post subject: Reply with quote

Good to know; I had no idea. Thanks!
Back to top
View user's profile Send private message
doob



Joined: 06 Jan 2007
Posts: 367

PostPosted: Sat Jan 22, 2011 7:40 am    Post subject: Reply with quote

If you're using D2 (in some cases D1 as well) then you can use a stack allocated struct instead of a class to have it behave as a scoped class.
Back to top
View user's profile Send private message
RobotGymnast



Joined: 06 Jan 2011
Posts: 23

PostPosted: Sun Jan 23, 2011 11:41 am    Post subject: Reply with quote

Unfortunately, that disables all use of delegates with those objects. I use delegates heavily with my objects. This isn't a problem in D as a whole, since letting garbage-collection take care of deletion is fine, but not in the case of DerelictSDL, where it's time-sensitive, and exceptions are thrown if things aren't scoped or explicitly de-allocated.
Back to top
View user's profile Send private message
doob



Joined: 06 Jan 2007
Posts: 367

PostPosted: Tue Jan 25, 2011 12:11 pm    Post subject: Reply with quote

I'm not quite sure I understand but your example above would work with a struct instead of a class.
Back to top
View user's profile Send private message
RobotGymnast



Joined: 06 Jan 2011
Posts: 23

PostPosted: Tue Jan 25, 2011 4:01 pm    Post subject: Reply with quote

Nested functions don't work with scoped-destruction objects, like scope classes or structs. A scope class may not be used in a closure, and all nested functions are closures.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic     Forum Index -> Derelict All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group